PVR driver
authorJustin Dou <Justin.Dou@intel.com>
Thu, 3 Mar 2011 12:15:22 +0000 (20:15 +0800)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:28:16 +0000 (12:28 +0300)
commit f0caf5295ff37b0f4ecb39b6b12f9f61b83f5eec
Author: Charles Johnson <charles.f.johnson@intel.com>
Date:   Tue Oct 11 14:01:37 2011 +0300

    GFX: Fix display init by moving mdfld_dsi_pkg_sender_init() earlier

    The DSI-LVDS bridge driver code moved the mdfld_dsi_pkg_sender_init() call
    later in mdfld_dsi_output_init(). This breaks display init for command mode
    panels, so move it back.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 23bb3b4c739813c0e461d0c00143b8ccb0bdfd12
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Oct 18 11:06:37 2011 +0300

    gfx: pvr: drop Moorestown specific files

    Remove unused Moorestown specific files in PVR.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 989d469cf7e30d79933c46ac981e8eaea159d9e3
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Oct 18 10:49:23 2011 +0300

    gfx: display: drop support for Medfield A0

    Remove hacky workarounds for an old board revision.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 895910f95ab83852ad7b9ea48e73d5abd151ec11
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Oct 18 10:29:28 2011 +0300

    gfx: pvr: drop #ifdef CONFIG_X86_MRST

    Moorestown is not supported. Remove code paths depending on
    CONFIG_X86_MRST=y.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 5412b558670e148323100475a466d54f2968718e
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Oct 18 10:28:03 2011 +0300

    gfx: display: drop #ifdefs on CONFIG_X86_MRST

    Moorestown is not supported. Remove code paths depending on
    CONFIG_X86_MRST=y.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 1654d116601bc06ee8c0576b0ebcc6aa3e5430d3
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Oct 18 10:13:19 2011 +0300

    gfx: display: drop IS_FW_UPDATED macro

    Yes, let's assume we really have updated the firmware. Remove IS_FW_UPDATED
    macro, unconditionally defined as 1, and regard it as 1.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit eeb911cf7a55c36df4c1f3acb7cdf17d703217e7
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 17:53:18 2011 +0300

    gfx: display: fix a number of compiler warnings

    Fix some compiler warnings.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit b204c62730c2ddb8a89f231928476a598b1b8121
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 17:33:48 2011 +0300

    gfx: imgv: drop Lincroft topaz support

    Lincroft is not relevant for Medfield. Remove Lincroft topaz support.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit c6b25a0bc70b5627f03ba335797c04412dbd5662
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 17:02:11 2011 +0300

    gfx: display: clean up psb_drv.h a bit

    The psb_drv.h has accumulated excess cruft. Tidy it up a bit, removing
    unused code.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 8e7642d52cfbf2e0a25c4088dc80aa7783a909f3
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 16:46:09 2011 +0300

    gfx: display: drop unused i2c module

    Remove unused code left behind in earlier cleanups.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 39de15266755794e0defa94d3639478bc5d98114
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 16:37:47 2011 +0300

    gfx: display: drop unused modes support

    Remove unused code left behind in earlier cleanups.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit a7c57928751bcaf932d0d56dc19701c651d5ad54
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 14:33:49 2011 +0300

    gfx: display: drop unused Pyrenees panel support

    Remove unused and bitrotting panel driver.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 5e1855228771a00d5cc44f850720c16f57456a69
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 14:23:14 2011 +0300

    gfx: display: drop unused BIOS support files

    These BIOS routines are not used in Medfield. Remove them.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 46b2bed9b7e628763751f2d19e871ab5dad9b96d
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 14:20:36 2011 +0300

    gfx: display: drop the rest of the unused LVDS code

    Keep purging LVDS related code not relevant in Medfield.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 676b6125308e5cee924a124a81b796b73f0a0526
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 14:12:12 2011 +0300

    gfx: display: drop unused SDVO support

    SDVO is not supported in Medfield. Remove the code.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit f32caf1bb703c5bd2f769dad960626f2deb4f62c
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 14:08:59 2011 +0300

    gfx: display: drop unused Aava DSI display driver

    Remove unused and bitrotting display driver.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit e45e1c13d1de3ff7542bf4725154a834af4c0b78
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 14:06:29 2011 +0300

    gfx: display: drop unused Moorestown DSI files

    Remove Moorestown specific DSI support code.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 34903fb8888caec18249d1c38660676d34f42fbb
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 13:59:20 2011 +0300

    gfx: display: clean up unused backlight functionality

    Remove backlight related code not relevant in Medfield.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 193157347041dbc678b4875d15c80b0b624152b5
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Oct 14 14:46:54 2011 +0300

    gfx: display: remove unused watchdog functionality

    Remove watchdog related functionality that is not used on Medfield.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 6cce56805947da0bcd6e9a4d585e3b55b6c7cacc
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Oct 14 14:39:10 2011 +0300

    gfx: display: remove unused Poulsbo lid related functionality

    Drop Poulsbo specific code related to lid.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 14e00f79b5ba7f94628dfefa26bc0f6396f0e302
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 13:53:36 2011 +0300

    gfx: display: clean up display and LVDS support, dropping unused code

    Focusing on Medfield support only allows us to drop unused and bitrotting
    code.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 40c24db86884cc1804ca4d30f8b57515e33d50c4
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 12:31:23 2011 +0300

    gfx: topaz and msvdx are always enabled in Medfield

    Topaz and msvdx are present in Medfield. Remove IS_TOPAZ() and IS_MSVDX()
    macros and consider them always true.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 7b2b1ae58b2ce07ea2f43fc0f25ef822b52cbb69
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 12:27:43 2011 +0300

    gfx: drop non-Medfield support

    Drop support for anything other than Medfield. Remove IS_MDFLD() macro and
    consider it always true.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 00d0cfba8f7fafc2f9f901896eb8d928698f14ce
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 12:06:25 2011 +0300

    gfx: drop Moorestown support

    Drop Moorestown support. Remove IS_MRST() macro and consider it always
    false.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 5be8a9e6524f5eb9caf9aacb2010fca52280f1bb
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 11:34:44 2011 +0300

    gfx: display: drop Moorestown MM support

    Drop Moorestown MM support. Remove IS_MRST_MM() macro and consider it
    always false.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit ec418c2d3342dce4c66cbbc14bbe08f1338dddd0
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 11:32:30 2011 +0300

    gfx: display: drop Oaktrail support

    Drop Oaktrail support. Remove IS_OAKTRAIL() macro and consider it always
    false.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit d3b4ea082fdc2d9a6c27f9457a0e09d8dad6b9fe
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Oct 17 11:30:55 2011 +0300

    gfx: display: drop non-MID support

    Drop non-MID support. Remove IS_MID() macro and consider it always true.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 2d12c777b382a51c9273b79ebe48d586299085de
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Oct 14 14:08:32 2011 +0300

    gfx: display: drop Poulsbo support

    Drop Poulsbo support. Remove IS_POULSBO() macro and consider it always
    false.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 8ac4007de566b708e1daed763c1b703bb28de1e9
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Oct 14 12:29:57 2011 +0300

    gfx: display: Initialize DSI-LVDS bridge chip only when it's used

    Fix modular build, but does not allow the module to be unloaded.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 74a69ce53506de2d7970b497f89440553bfbe3ba
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Thu Oct 13 17:43:00 2011 +0300

    Revert "graphics: Fix build as module"

    This reverts commit "graphics: Fix build as module", which oopses on
    graphics driver probe.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit ede699dc31f726bc06d65f09d17e485e0e39cabc
Author: Alan Cox <alan@linux.intel.com>
Date:   Thu Oct 13 10:41:23 2011 +0100

    gfx: drop Moorestown support

    First step at dropping Moorestown support: don't build it. This is part of
    a larger commit in AC tree filtered to drivers/staging/mrst.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 379b9b51688ed33cd2385954cfd61350ad7d6756
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Oct 13 14:36:19 2011 +0100

    gfx: pvr: change SECURE_FD_EXPORT compile option into a run-time check

    At the moment we need to support user space libraries compiled both with
    and without this option on. Check which library is in use and change the
    functionality accordingly.

    Note that this option is only a poor workaround for a problem in user
    space. Once we have a proper fix there, we can remove the corresponding
    code here.

    Also move -DSUPPORT_MEMINFO_IDS to where similar defines are specified
    and remove -DPVR_SECURE_HANDLES which is already specified elsewhere.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 8cfeef14fa2f72e68ba7c87f67ced2ad8776a918
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Oct 13 14:36:18 2011 +0100

    gfx: pvr: prepare for build options that can mismatch

    Needed by the next patch.

    We need a place for options bits that user space can pass to the driver.
    These bits - unlike the current compile option bits - will not be
    compared to the driver's compile option bits, the same driver binary will
    support user space libraries both with these bits on or off.

    Also sanitize some of the debug/error prints.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 4862da2e2dcf43226b7b66d8eee4c7e840144ae4
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Oct 13 14:36:18 2011 +0100

    gfx: pvr: add pvr_get_sgx_dev_info

    Factor out this functionality to its own function and use it in the
    spot where it was inlined earlier.

    Needed by the next patch.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit c2db37c90938424be4b9493f2b2615d17f37a140
Author: Pauli Nieminen <pauli.nieminen@linux.intel.com>
Date:   Thu Oct 13 14:36:18 2011 +0100

    gfx: pvr: Add dummy ioctl entry for a new UMG ioctl

    To have same ABI with HC userspace we need stub ioctl entry for a new
    UMG ioctl. The ioctl is to query current buffer index from swapchain.
    But we have depracated swapchain support in kernel so no point
    implementing the ioctl.

Signed-off-by: Pauli Nieminen <pauli.nieminen@linux.intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 62fd2f750283b44a0ec529ec6d32889ed0e9fab6
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Oct 13 14:36:17 2011 +0100

    gfx: pvr: check also the PVR specific retval of IOCTLs

    In addition to the standard IOCTL error return, the PVR driver can
    return a custom error code in it's IOCTL out structure. Check for this
    too.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 16a1c431f86110e8d3d19bcc1b57ecb9afb7b708
Author: Imre Deak <imre.deak@intel.com>
Date:   Wed Oct 12 19:22:47 2011 +0100

    gfx: pvr: add white list based firmware version check

    Do this to support multiple SGX firmware versions. Until now there had
    to be an exact match between firmware and kernel driver versions, which
    made maintenance of the kernel driver difficult. This change is the
    beginning of a series of changes that relaxes the user
    space/kernel/firmware dependency as much as possible and allows us to
    have a single kernel driver for all supported configurations.

    Also do some error/debug printing sanitizing on the way.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 39897129184c47ea32ef87917c88a7d7bb3165cd
Author: Imre Deak <imre.deak@intel.com>
Date:   Wed Oct 12 19:22:46 2011 +0100

    gfx: pvr: check sizes of IOCTL parameter structures

    This sanity check can be done easier using the IOC_* macros for
    well-written IOCTLs. In case of PVR IOCTLs we have to do them manually,
    since each input/output IOCTL parameter is accessed through an extra
    redirection from a fixed IOCTL structure that is the same for every PVR
    IOCTL.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 50ee3670f22df7525b83dfe163c3586afcbf79b5
Author: Imre Deak <imre.deak@intel.com>
Date:   Wed Oct 12 19:22:46 2011 +0100

    gfx: pvr: add convenience variable

    Needed by the upcoming patch.

    Also sanitize a debug printing on the way.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 96b148ad595dd104c7a2f0d06d0fae6cd0e090c3
Author: Imre Deak <imre.deak@intel.com>
Date:   Wed Oct 12 19:22:45 2011 +0100

    gfx: pvr: fix IOCTL ABI w.r.t SGX kick IOCTL

    Recent PVR user space library versions extended the parameter structure
    of this IOCTL effectively changing the ABI. Fix the structure
    accordingly.

    bLastInScene is supposed to optimize on some of the cache flushes before
    starting a rendering operation. It's still under investigation whether
    it's safe to do this though. Until we figure this out, ignore this
    parameter and perform cache flushes as before.

    SGX_MAX_SRC_SYNCS is the maximum number of source buffers per render
    operation for which buffers we can do a dependency check.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 30fee8cb6bd1ef947c80aa927a8b4bdfffa674d5
Author: Imre Deak <imre.deak@intel.com>
Date:   Wed Oct 12 19:22:45 2011 +0100

    gfx: pvr: fix IOCTL ABI w.r.t MEMINFO_IDS, SECURE_FD_EXPORT, SECURE_HANDLES

    Recent PVR user space library versions extended some of the IOCTL
    parameter structures, effectively changing the ABI. These extensions
    are optionally built based on the above Kconfig options. They are
    in fact only workarounds for problems in those library versions, so
    after we fixed those problems in the libraries properly we shoud remove
    the support for them in the driver.

    For other library versions not depending on these features, enabling
    them won't have any functional difference. The net result is that we
    remove the ABI dependency and can use both types of library versions
    with the same driver binary.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 5e809df345a679f2d99bf79cfbba041ab33bed99
Author: Pauli Nieminen <pauli.nieminen@linux.intel.com>
Date:   Fri Oct 7 15:36:19 2011 +0300

    gfx: Use drm mode page flipping also in medfield

    The page flip was originally developed and tested using mrst prototype
    but same code works correctly in medfield too. To enable flip support
    driver has to add the flip function to medfield crtc function pointers.

Signed-off-by: Pauli Nieminen <pauli.nieminen@linux.intel.com>
commit dd97cf8808b283727a0b7114268559db43536c16
Author: Alan Cox <alan@linux.intel.com>
Date:   Mon Oct 3 12:46:53 2011 +0100

    graphics: Fix build as module

    One module_init only

Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 122715042e4127e8fa27fb745ae0ae405e9a9fef
Author: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Date:   Fri Sep 30 12:52:44 2011 +0100

    pvr: drv: implement drm page flip ioctl

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit d6171d71d2839559253d9bf0c33bcba4271f73f8
Author: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Date:   Fri Sep 30 12:52:43 2011 +0100

    pvr: srvkm: add a callback based sync mechanism

    Users of this mechanism can register a callback that will be called
    when the specified sync object's completed ops turn to be greater or
    equal to the current pending values. If the specified object is already
    in sync, the callback will be called immediately. The flags control
    whether read, write or both types of operations should be considered.

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit a881d79a4ef3d994de797e6910cd3f24e3b06b28
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 20 16:54:00 2011 +0300

    GFX: Add tc358764xbg/65xbg MIPI DSI-LVDS bridge chip support

    Add preliminary support for Toshiba tc358764xbg/65xbg MIPI DSI-LVDS bridge
    chip. Set panelid=TC35876X on the kernel command line to enable support.

    ISSUES/TODO:

    * The I2C device and GPIO line numbers should be defined in firmware,
      rather than hard coded in the driver. Consequently, this implementation
      only works on dv0.9.

    * The driver exposes functions that are called from here and there in the
      display controller driver, even before the driver has been initialized.

    * The implementation touches DSI clock registers, among other things,
      directly without locking. It seems to usually work by accident.

    * Many of the problems in the implementation (like the above) come from the
      fact that the whole display controller driver lacks proper infrastructure
      for pretty much everything, including easily adding new display
      drivers. It's not trivial to fix this when adding a new driver.

    * Fix checkpatch/sparse errors.

    This patch is based on earlier work by (at least) Srinivas Pandruvada, Paul
    Drews, Ke Ai, and Michael Demeter.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 6e9f8dd97fc07f19c47f3d4160ce442aecbac830
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Sep 23 17:16:28 2011 +0300

    GFX: Redefine register addresses with pipe parameter

    Replace MIPIA_SOME_REG + reg_offset constructs with MIPI_SOME_REG(pipe)
    macros to simplify error prone code and to improve readability.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 7e5a33bdbd3297c75b69bfd2a802a8da582f3629
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Sep 23 10:40:15 2011 +0300

    GFX: Remove duplicate DSI controller init code

    DSI controller init functions dsi_controller_init(),
    dsi_controller_dpi_init(), and dsi_controller_dbi_init() are mostly just
    duplicates of the corresponding functions with mdfld_ prefix. Handle the
    minor differences, and remove code duplication.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 2fa11c603a4c95edcedc6333310e5184cba8da9c
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 16:39:53 2011 +0300

    GFX: Remove redundant and unused ioctl definitions

    Remove redundant, unused, and commented out ioctl definitions.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit f24b654d4a226490a9ba753ae722014da78acae6
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 14:45:33 2011 +0300

    GFX: Remove another useless DSI command send wrapper

    Use mdfld_dsi_send_mcs_short() directly rather than through a wrapper.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit b901ccfe425f89686f8b1149cdf21f2912c39c21
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 13:07:13 2011 +0300

    GFX: Replace the BIT<N> macros with the generic BIT(N) from bitops.h

    Replace BIT<N> macros with generic BIT(N) macros from bitops.h. The bulk of
    the change was done using sed:

    sed -i 's/\([^A-Za-z0-9_]*\)\(BIT\)\([0-9][0-9]*\)\([^A-Za-z_]*\)/\1\2(\3)\4/g' *.c *.h

    Then manually dropped the #defines from psb_intel_reg.h.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 4088df73c3ca8d050db82b19c20e6733ec34cd74
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 12:28:12 2011 +0300

    GFX: Make display config mode getter functions static

    The display config mode getter functions are used through function pointers
    within struct panel_funcs, so they can be static.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 1bfa41a52df2f3e7540afd8bab26c6dce3aa5a43
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 12:26:10 2011 +0300

    DRV: Remove unused display header files pyr_vid.h and tmd_cmd.h

    The display header files pyr_vid.h and tmd_cmd.h contain only declarations
    for functions that don't even exist. Remove the files.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 5eb3e79030f0b0e528af5c46848cbd69a49da7ec
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 12:12:45 2011 +0300

    GFX: Remove useless unreachable BIT macros

    Remove useless #defines within #if 0.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit b7ab02155911f5fd8221282a30301ad802bf37f4
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 12:01:37 2011 +0300

    PVR: Drop support for kernel versions 2.6.34 and older

    There is absolutely no guarantee that the driver would work with kernel
    versions 2.6.34 or older, even with the conditional compilation in place,
    and the further modifications that will be made to the driver won't take
    older kernels into account anyway. Thus explicitly drop support for 2.6.34
    and earlier instead of pretending.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit ed996159001324249dc71a12e7bd60202e21014d
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 11:50:09 2011 +0300

    GFX: Drop support for kernel versions 2.6.34 and older

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 3cc85dd6288c5b7bd4a8f6e05ab99c346850a330
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 11:41:18 2011 +0300

    GFX: Drop support for kernel versions 2.6.34 and older

    There is absolutely no guarantee that the driver would work with kernel
    versions 2.6.34 or older, even with the conditional compilation in place,
    and the further modifications that will be made to the driver won't take
    older kernels into account anyway. Thus explicitly drop support for 2.6.34
    and earlier instead of pretending.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 018d062de792c070e2d0bea469421ae8b6a4dd78
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Sep 6 10:56:18 2011 +0300

    GFX: Remove unused dsi pkg structs

    The mdfld_dsi_{gen_short_pkg,gen_long_pkg,dcs_pkg,pkg} structs are no
    longer used and can be removed.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit fad1f6978e0138126e41fe183ba25c02a806fb90
Author: Pauli Nieminen <pauli.nieminen@intel.com>
Date:   Wed Sep 7 18:00:27 2011 +0300

    pvr: Free export handle only after memory is freed

    Export handles are currently freed when the exporter frees it local
    mapping of the memory. Next export may (is very likely) to reuse the
    handle for different memory.

    While process that received the export handle wants to avoid expensive
    memory mapping when it already has mapped a matching handle. If the
    memory behind a handle changes suddenly process receiving process will
    continue use old memory.

    Problem can be seen in screen that random client would lose content
    because it renders to old memory while display server shows the new
    memory in screen.

    The fix is to delay the free of the handle until the memory is freed.

Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
commit c3c6c7df9ac604855c99a9d05a7b8bef8495e264
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Sep 1 18:01:28 2011 +0300

    mrst: pvr: add debugfs support

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit bc6de1ede5c35870d1113fe0ef6c90b0f1e8f473
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Sep 1 18:01:27 2011 +0300

    mrst: pvr: add tracing for flip command

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 193f1a94f45e820085bc3402b2c72f6ee103b57e
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Sep 1 18:01:26 2011 +0300

    mrst: pvr: add tracing to SGX queryblits command

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit eea730158b268d0df9a3d96e3c95887b6393a9c0
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Sep 1 18:01:25 2011 +0300

    mrst: pvr: add tracing to the SGX kick and transfer commands

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit ea703813ba51bedf059ff4a182a845f2235d6b55
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Sep 1 18:01:24 2011 +0300

    mrst: pvr: pass proc info to various IOCTL handlers

    Needed by the next patch adding tracing to these commands.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 71249e1b27c430b522cd4919af413bc136356d91
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Sep 1 18:01:23 2011 +0300

    mrst: pvr: add command tracing support

    Add a lightweight tracer to track commands submitted by clients. This
    can help for example to debug dead-lock situations where command
    synchronization counters form a circular dependency.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 447184e302d7efc0577fc16b181203bbb2f6e7f8
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Sep 1 18:01:22 2011 +0300

    mrst: pvr: include missing header files

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 129c16270bb4c2190d2a15c77fb61aec984a5454
Author: Imre Deak <imre.deak@intel.com>
Date:   Thu Sep 1 18:01:21 2011 +0300

    mrst: pvr: get proc name during process attach time

    This will be needed by the upcoming patches where we need a cheap way
    to get to the current process name.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 77bf123bd4a87cb6355133037c25601200b2fc60
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Aug 26 14:56:27 2011 +0300

    GFX: Replace out-of-range udelay() with mdelay()

    Fix build error:

    ERROR: "__bad_udelay" [drivers/staging/mrst/medfield/medfield_gfx.ko] undefined!

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit f7fdba671596913b63fd4f11f1b88c71425c50ae
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Wed Aug 24 12:49:53 2011 +0300

    GFX/PVR: Clean up function and variable declarations

    Make more functions and variables static, and remove a few unused
    variables. Move most extern declarations scattered around inline in .c
    files to .h files, and add proper #includes. This helps tracking the
    dependencies between modules, and also fixes a number of sparse warnings.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit ae6010f7d2694bde629955de56c74e8c4287e1ce
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 23 16:08:18 2011 +0300

    PVR: Delete unused header file sysirq.h

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit f7d2693a454cc6d393d1e0691fce060d84b065b0
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 23 16:07:20 2011 +0300

    GFX: Remove duplicate declarations for psb_irq.c functions

    Declare functions in psb_irq.c only in psb_irq.h, not also psb_drv.h.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 38051b54f4093d0fac3f188770feb1006203cd85
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 23 15:21:37 2011 +0300

    GFX: Delete unused files psb_intel_dsi2.c and psb_setup.c

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 2c8cfd18094037e23698e20d2059de14f4b55cc0
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 23 10:12:42 2011 +0300

    GFX: Reserve mdfld_dsi_send_dcs() for mem write command only

    mdfld_dsi_send_dcs() is mostly about handling mem write as a special case,
    passing other commands to other functions. Only use the function for mem
    write.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 7f2e39a3b86a73bc7b0125a891d360658da41d10
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 23 09:37:17 2011 +0300

    GFX: Pass DSI command data as data and length instead of struct

    Pass DSI command data as data and length, and go on with the mdfld_dsi_pkg
    struct removal.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit f57208f9d8094b1cc6fd248588d8a9fbad4e0288
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Aug 22 18:06:20 2011 +0300

    GFX: Clean up the low level DSI sender functions send_{short,long}_pkg()

    Also keep removing the mdfld_dsi_pkg struct from DSI sending.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 84e21960c8fa8d3ba499f0394c8df754db4ee0c2
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Aug 22 17:04:09 2011 +0300

    GFX: pkg_type is really the MIPI DSI data_type, rename it accordingly

    The data_type is used in registers, but the definitions come directly from
    MIPI DSI specs. Rename the enums accordingly. Also drop the unused and
    non-existent DCS packet type.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 2f95aa967f0a96ce54943d6bdffc73acb9ebd128
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Aug 22 11:52:14 2011 +0300

    GFX: Make transmission mode a bool parameter to simplify code

    Make transmission mode a bool parameter to simplify code. This is also in
    preparation for further simplifications later.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit f0d40649f1e595ee6017e8b38aa36b15d057e107
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Aug 19 13:55:58 2011 +0300

    GFX: Remove queued DSI command sending

    The queued DSI command sending was overly complex, buggy (for example
    keeping pointers to past stack frames or deallocated data), limited (number
    of commands in queue, data size in command), and it was only used in a
    couple of places. Simply remove it, and send all DSI commands immediately.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit a4b4942508f634fd8bd13165d46d4d6db142ad4a
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Aug 19 12:43:22 2011 +0300

    GFX: Hide dsi_pkg_sender internal structs and enums

    Move some structs and enums from .h to .c. This makes later refactoring of
    mdfld_dsi_pkg_sender.c easier.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 5c44bbec1a1768791a740c7733b3e4689c2bff7e
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Thu Aug 18 14:25:52 2011 +0300

    GFX: Remove a useless abstraction layer in DSI command sending

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit e666aef44b106bae04fb65f7e068665bb3079882
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Thu Aug 18 12:58:03 2011 +0300

    GFX: Remove an abstraction layer for some DSI commands

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit ef071cdccaafeed42229af9e6265c7867e84ffe2
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Thu Aug 18 12:38:32 2011 +0300

    GFX: Refactor: Make DSI HS/LP a parameter rather than an abstraction layer

    This is a start towards a more sensible DSI command interface.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit affbb07de18e381824e722c1794e07c7acb3c8cf
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Wed Aug 17 16:27:19 2011 +0300

    GFX: Fix a number of sparse warnings

    Fix issues found by sparse: Make functions and variables static where
    possible. Use NULL rather than 0 for pointers. Use __iomem to reduce
    address space warnings. Remove some unused variables and functions. Fix
    locking imbalance. Use unsigned types for 1-bit bitfields.

    Note: Only sparse warnings are fixed in the changed code, which means this
    will produce checkpatch warnings.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 2d70898399fbf8cf515a2a93bd46c69265a5ff84
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Wed Aug 17 16:30:41 2011 +0300

    GFX: Do not include .c file from another

    Simply append psb_intel_display2.c to psb_intel_display.c rather than
    include it.

    Note: This patch generates lots of checkpatch warnings, because the
    included file is inserted as-is, without modification.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit f1c8ab0bfbeff46fe6a1cea3c5afb7f25265d8db
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 16 13:07:41 2011 +0300

    GFX: Quick fix to silence build warnings about unused procfs functions

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 9e82f9fcbf6f9fb508c2c090c5a49813da5a015e
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 16 13:04:06 2011 +0300

    GFX: Quick fix to silence build warnings about unused variables

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 5408ea71f8a7bdae8d03089d48986746dd57b272
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 16 13:01:21 2011 +0300

    GFX: Fix build warning about unused backlight related function and variables

    Add #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE around the function and variables.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit abfe9e60cf2acc0cde07dcbe9229219c90f6113a
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Aug 16 12:55:25 2011 +0300

    GFX: Fix printk format warnings

    Reduce build noise by fixing printk format warnings.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 6906b5a242fe460827f0b43f0e270d8461ac02dd
Author: Jani Nikula <jani@nikula.org>
Date:   Tue Aug 16 10:56:18 2011 +0300

    PVR: Fix PVR build so that it doesn't get rebuilt every time

    Use symlinks instead of copies of the source files, and preserve them using
    .PRECIOUS to 1) build the driver so that it doesn't get rebuilt every time,
    and 2) produce useful paths in the build log that point to the actual
    source files through the symlinks. Add the intermediate symlinks to
    .gitignore.

    This is a slight improvement to the original hack of building more than one
    kernel module from the same sources with different config options and
    defines. It should be fixed later, but this makes life easier now.

    Also make the Medfield and Moorestown Makefiles as similar to each other as
    possible, to make later unification easier.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit bb926aae8fbb0cfb98f387e504337ac3c01147d0
Author: Pauli Nieminen <pauli.nieminen@intel.com>
Date:   Tue Aug 16 14:02:40 2011 +0300

    pvr: Remove timer hack from vblank handler

    The timer hack isn't required after userspace fixes to flip
    implementation.

Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 6ccfe7bacbffc1900add826fb1f4efa0bc40702a
Author: Pauli Nieminen <pauli.nieminen@intel.com>
Date:   Thu Aug 11 09:31:21 2011 +0300

    pvr: Fix device poll implementation

    Driver always signaling that there is data available misleads display
    server to call blocking read. Blocked display server makes whole
    system unuseable.

    drm_poll checks if there is queued events to userspace. Replacing
    psb_poll with drm_poll fixes the poll implementation.

Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 5fef5630c4fddd4c775c91c0ba11c468af001cc2
Author: Alan Cox <alan@linux.intel.com>
Date:   Fri Aug 19 14:05:32 2011 +0100

    gfx: Fix build failure of graphics when compiling for MRST

    The graphics code tries to use RAR headers which are not where it expects. We
    don't use the RAR feature or care about it for the this GFX driver so throw
    it out.

Signed-off-by: Alan Cox <alan@linux.intel.com>
commit 803ff08d23f4f0164f24f664c23ce772724f8722
Author: Pauli Nieminen <pauli.nieminen@intel.com>
Date:   Fri Aug 19 14:05:17 2011 +0100

    Backlight type was missing from properties which caused warning in
    register.

Reported-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
commit ce064800f88e9731c1d1333fbccc4a05e8e4fc68
Author: Pauli Nieminen <pauli.nieminen@intel.com>
Date:   Fri Aug 19 14:03:20 2011 +0100

    pvr: Fix out of array access

    PVR driver defines its own connector and encoder types for display which
    aren't suppported by drm code. When converting the type to string kernel
    would crash or output random junk because conversion table doesn't have
    entry for MIPI.

    [   19.455764] BUG: unable to handle kernel paging request at 65646f6d
    [   19.455779] IP: [<c127e0c9>] strnlen+0x9/0x20
    [   19.455802] *pde = 00000000
    [   19.455812] Oops: 0000 [#1] PREEMPT SMP
    [   19.455825] Modules linked in: medfield_gfx(C+) fbcon font bitblit
    softcursor ttm drm_kms_helper drm fb fbdev
    +cfbcopyarea cfbimgblt cfbfillrect
    [   19.455860]
    [   19.455871] Pid: 129, comm: modprobe Tainted: G         C  3.0.0+ #30
    [   19.455884] EIP: 0060:[<c127e0c9>] EFLAGS: 00010297 CPU: 0
    [   19.455895] EIP is at strnlen+0x9/0x20
    [   19.455903] EAX: 65646f6d EBX: f86ccd60 ECX: 65646f6d EDX: fffffffe
    [   19.455912] ESI: f86ccd80 EDI: 0000ffff EBP: f5b596fc ESP: f5b596fc
    [   19.455922]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
    [   19.455932] Process modprobe (pid: 129, ti=f5b58000 task=f6312be0 task.ti=f5b58000)
    [   19.455940] Stack:
    [   19.455945]  f5b5971c c127bb3f f999f67b f86c8b25 65646f6d f5b59784 f86ccd60 00000002
    [   19.455965]  f5b59760 c127cad6 00070100 0006ffff 0006ffff 00070190 00060010 0006000c
    [   19.455985]  00000020 f86ccd60 f86ccd80 f86c8b27 ff0a0004 ffffffff 0000000b f63b44f8
    [   19.456005] Call Trace:
    [   19.456021]  [<c127bb3f>] string.isra.4+0x2f/0xb0
    [   19.456133]  [<f999f67b>] ? mdfld_dsi_gen_fifo_ready+0x3b/0xb0 [medfield_gfx]
    [   19.456151]  [<c127cad6>] vsnprintf+0x1e6/0x3a0
    [   19.456166]  [<c127ccea>] snprintf+0x1a/0x20
    [   19.456210]  [<f86bb287>] drm_get_encoder_name+0x37/0x40 [drm]
    [   19.456231]  [<f876fac5>] drm_crtc_helper_set_mode+0x405/0x470 [drm_kms_helper]

    MIPI (or DSI) is protocol specification on top of LVDS serial bus. That
    makes it resonable to call MIPI connectors and encoders LVDS.

    NOT FOR UPSTREAM

Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
Reported-and-Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
commit e6a9e72108f5444b754d68dd60328e0a8740ab36
Author: Pauli Nieminen <pauli.nieminen@intel.com>
Date:   Fri Jul 8 11:04:57 2011 +0300

    configs: Update medfield config to have touch&keypad support

Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 27a326770da336624834f101ff889421dae1b007
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Tue Jul 5 11:19:08 2011 +0300

    mrst: Add drivers/staging/mrst/README documenting the forward port

    Document where the driver is coming from and what was done to make it work
    against linux-3.0-mid-ref.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit c8355336d838d0e19135783dbf0bb60504bcbd14
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 17:46:02 2011 +0300

    mrst: Add arch/x86/configs/medfield_pvr_defconfig

    Add a known good defconfig.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit c5a69015cba9486adab91a987d13ed8698db8368
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 15:14:23 2011 +0300

    drm: Protect drm/drm_os_linux.h inclusion with #ifdef

    Fix problems caused by including both drm/drmP.h and drm/drm_os_linux.h.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 353c55ac88cf9525fea65d797723c5538967915c
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 14:51:43 2011 +0300

    drv: Add DRM_MODE_CONNECTOR_MIPI definition

    REVISIT: This definition and value 15 are from the linux-3.0-mid-ref
    tree. psb_intel_dsi.c also has a commented out definition with value
    13. The definition should be added to include/drm/drm_mode.h eventually.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 37a03b495ca98bee1adcb391e47a411d5aa82e77
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 14:44:07 2011 +0300

    drv: Remove psb_validate_kernel_buffer() and val_seq

    The function does not compile, is not used, and is the only user of
    val_seq, after ttm_eu_reserve_buffers() has switched to handling the seq
    internally.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 11ef8154687d734ba0d4d4238c6101e826de1b9e
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 14:26:47 2011 +0300

    drv: Use bdev->fence_lock for locking

    The lock field has been dropped from struct ttm_buffer_object. Use the
    bdev->fence_lock of the struct for locking instead.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit d19a6a3dc015ff165f79a286fd5ba416d992f81e
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 14:15:36 2011 +0300

    drv: Add force parameter to struct drm_connector_funcs .detect functions

    An additional force parameter has been added to the .detect function in
    struct drm_connector_funcs. Add the parameter to the functions
    dsi_connector_detect, mdfld_dsi_connector_detect, mdfld_hdmi_detect,
    mrst_dsi_detect, psb_intel_lvds_detect, and psb_intel_sdvo_detect.

    FIXME: Start actually using the force parameter.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 52ebe11a7cf8c0ca37bef03c0cc411d63bfcfc84
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 14:12:54 2011 +0300

    drv: Add start parameter to psb_intel_crtc_gamma_set()

    The start parameter has been added to struct drm_crtc_funcs .gamma_set
    function, so add it to psb_intel_crtc_gamma_set() also.

    REVISIT: Start using the start and size parameters in the function.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit b8a0cd91217e0395ca402e3a6a4c34ae2d233494
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 14:01:04 2011 +0300

    drv: Remove initializations that have been removed from struct drm_driver

    REVISIT: The procfs stuff should be ported to sysfs/debugfs.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit d82d658906ca20cff1758f776f414fb48897fcc9
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 13:57:28 2011 +0300

    drv: Separate the drm driver and pci driver structs

    The pci_driver struct is no longer part of struct drm_driver.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 266d1b7ace965b1203f7de738568fc325d1dd77f
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 13:11:27 2011 +0300

    drv: Replace acquire/release_console_sem with console_lock/unlock

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit d3301724bfd035c91d5c561d1f38c2753835526f
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 13:03:54 2011 +0300

    drv: Remove #include <linux/i2c-id.h>

    The linux/i2c-id.h file has been removed.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 4613ef2bd9389b10779cdde1b2239f26d727604c
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 13:23:14 2011 +0300

    drv: Remove an informational message

    The code block would not compile, because struct ttm_mem_type_manager no
    longer has manager field. Instead of resolving the issue, just remove the
    code block because it only prints an informational message if "GATT was not
    clean after VT switch".

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 1546b44a62af1eb1dd72f14be2736a049b5101cc
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 13:20:45 2011 +0300

    HACK: drv: Do not use BKL for drm_ioctl() locking

    The BKL no longer exists, do not use it. This is a hack because the BKL is
    not replaced with any other locking.

    REVISIT: Need to check the locking.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 55218c31dfe2a3e597df144ab4007f5fae473928
Author: Pauli Nieminen <pauli.nieminen@intel.com>
Date:   Mon Jul 4 22:16:37 2011 +0300

    pvr: Add bo manager functions to custom memory managers

    FIXME: Check if pvr need custom memory manager like nouveau

Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit b8ed80804204bf769d8b8fe6f4681f92e56aea38
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 15:46:56 2011 +0300

    pvr: Replace ttm_global_reference with drm_global_reference

    struct ttm_global_reference has been dropped in favor of struct
    drm_global_reference.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 47818d739cf33acc766dd7af7a9eeb20f7a3c6aa
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 15:17:54 2011 +0300

    pvr: Use bdev->fence_lock for locking

    The lock field has been dropped from struct ttm_buffer_object. Use the
    bdev->fence_lock of the struct for locking instead.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 5f42477b7df47850047008bd2848f775dbb1fee3
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 15:36:52 2011 +0300

    pvr: Add dma_addrs parameter to drm_psb_tbe_populate

    The dma_addrs parameter has been added to struct ttm_backend_func .populate
    function. Add it to drm_psb_tbe_populate also.

    REVISIT: Is there a need to use the dma_addrs parameter?

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 838f8a6f87ba90aa3489a0ebd83c06bdc4a7db9c
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 15:34:01 2011 +0300

    pvr: Use the start field of struct ttm_mem_reg

    The mm_node field of struct ttm_mem_reg has become a void*, and can no
    longer be referenced.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit e81fb9c9f888ff477034b6dd63f18c5bb386d5d1
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 13:12:13 2011 +0300

    pvr: Replace acquire/release_console_sem with console_lock/unlock

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit b23657906cf1d8cd4c083d69021f9d69169b59ab
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 12:06:03 2011 +0300

    pvr: Use DEFINE_SPINLOCK() instead of SPIN_LOCK_UNLOCKED

    SPIN_LOCK_UNLOCKED has been removed.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 581bb8e42869ebce5e33e13262cb5e54d22a830d
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 11:59:22 2011 +0300

    pvr: Fix calls to pci_restore_state()

    Fix calls to pci_restore_state(), which no longer returns a value.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 38896d85369f49b2f8ca106d97708947df925bb0
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 11:48:23 2011 +0300

    pvr: Remove references to AUTOCONF_INCLUDED and linux/config.h

    AUTOCONF_INCLUDED is no longer defined, and linux/config.h no longer
    exists.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit fa229e9d85048d19a3b2de19b66d3a87eab8a2ca
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Mon Jul 4 11:47:35 2011 +0300

    mrst: Remove local versions of drm_global.{h,c}

    The mrst fork looks incorrect.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit f173452bed6a7384d258b11658ec55afe87fb71c
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Fri Jul 1 12:43:00 2011 +0300

    staging: Add mrst graphics driver to Kconfig and Makefile

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
commit 0aae9776ad86ab77dfe67cf549db78667a46ee62
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Jun 22 13:17:04 2011 -0700

    GFX: Graphics Driver build release 5.3.0.0047

    Weekly Graphics driver release.
    Please use usermode package 0047 with this build.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit de023b4f5dbbc6bdd5a4184c561727b2b2ac2df4
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Fri Jun 17 10:00:52 2011 -0700

    GFX: Enable Display Island for DPST

    When enabling DPST by default we need to make sure that
    display island is enabled to get DPST interrupt generated.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 35cc686f6a56cb1ee959a9ff68d557f9d19ac5a9
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Jun 16 12:31:04 2011 -0700

    GFX: Allow multiple registers dump

    Allow multiple registers to be dumped from procsys.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit f5b3a4c10c0a385471b8b65bede0509681a06626
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Fri Jun 10 11:42:42 2011 -0700

    GFX: Fix invalid return when creat_proc_init fails

    when init failed for any of the procfs creation the failure
    would be returned.  Now it just makes sure that error is printed
    and continued.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 75ede86757ffc57c2503b615b4172160b7284364
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Mon Jun 20 15:50:19 2011 -0700

    kernel rebase kernel-adaptation-mrst-2.6.37.6-102.1

commit 094854b8292dba86e57248f686efe35b8de425cd
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Fri Jun 17 10:00:52 2011 -0700

    GFX: Enable Display Island for DPST

    When enabling DPST by default we need to make sure that
    display island is enabled to get DPST interrupt generated.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit c92e91c54ab7d6d5e5d4c1df1156fef4088c8943
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Jun 16 12:31:04 2011 -0700

    GFX: Allow multiple registers dump

    Allow multiple registers to be dumped from procsys.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit a52a45c44aa5a807f8733abbdd8cf55c16b676f1
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Fri Jun 10 11:42:42 2011 -0700

    GFX: Fix invalid return when creat_proc_init fails

    when init failed for any of the procfs creation the failure
    would be returned.  Now it just makes sure that error is printed
    and continued.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit d25fe71cd95a6fe761315e882605b0e74f466eec
Author: Pauli Nieminen <pauli.nieminen@intel.com>
Date:   Thu Jun 9 11:03:20 2011 +0300

    moorestown/pvr: Enable memory debug only in debug build

    Memory debug flags have huge runtime footprint which can be seen
    as one of larges CPU users in system. In my QT/demos/declarative/snake
    profile cost was about 15% CPU time.

    Actual test case is GPU limited so optimization doesn't give fps boost
    but it maybe meaningfull optimization for applciation startup and
    shutdown times.

    Also fixing incorrectly typed DEBUG_LINUX_MEM_AREAS to actually enable
    the feature.

Signed-off-by: Pauli Nieminen <pauli.nieminen@intel.com>
commit 0d13a11049f84fa86d8029cb69baead764ccfa59
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Jun 9 09:02:49 2011 -0700

    GFX: Graphics Driver build release 5.3.0.0046

    Weekly Graphics driver release.
    Please use usermode package 0046 with this build.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit afb5c438c374397df4d3136d1a7c24850daa0f5f
Author: Ren, Zhaohan <zhaohan.ren@intel.com>
Date:   Wed May 11 15:56:48 2011 +0800

    Update psb_drm.h

commit 63ae47109df731c117a61ce523cf5473764f2f69
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Sat May 28 15:08:46 2011 -0700

    revert back to a 19ms display DMA delay for SwapChain buffers.

commit 96f710fdc9c4244562239af87571376c959598b7
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Wed Jun 1 11:09:03 2011 -0700

    Change DMA delay for when we have a swapchain to 3ms. This works well and pushs the image out without a delay.

commit e9205fb80d61a280812e96507e61ff29c538524a
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Tue May 31 18:05:55 2011 -0700

    Implement a different Display Buffer DMA delay from the VSYNC interrupt. This delay for the 60hz display refresh rate is 18ms for a QT rendered display and 11ms for a GLES2 rendered display.

commit 4106ee3e3a5d348868f5bcf7d3d3a8b6e2e83755
Author: Peter Zick <peterz@peterz-VirtualBox>
Date:   Tue May 31 13:10:15 2011 -0700

    Remove printk debug message from ospm_suspend_display.

commit 81022bb3d5da8696084fbc85949b4f35bfca78b1
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu May 19 16:11:37 2011 -0700

    GFX: Graphics Driver build release 5.3.0.0045

    Weekly Graphics driver release.
    Please use usermode package 0045 with this build.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 967dbe161d67b94f95bf7f2149ed07f1906a5803
Author: Peter Zick <peterx.zick@intel.com>
Date:   Fri May 27 09:24:05 2011 -0700

    GFX: Support graphics & Display island power gating.

    added to support the Moorestown configuration of the
    graphics and display islands power gating.

Signed-off-by: Peter Zick <peterx.zick@intel.com>
commit 14693c1032a9abb43c42d8d6c3240549c52a58b0
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Fri May 20 16:04:58 2011 -0700

    GFX: Change the jiffies use to proper function

    Use msec_to_jiffies() to insure an 11ms delay for the
    Display Buffer DMA timer.  Also set the display buffer DMA delay
    to 18ms.  This is to optimized for QT/MeeGo-ux.

Signed-off-by: Daemon Anastas <daemonx.g.anastas@intel.com>
commit ce09e906f985b0894f614943cacf533839871b83
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Fri May 27 15:42:48 2011 -0700

    kernel rebase to kernel-adaptation-mrst-2.6.37.6-54.2

commit 48a951768628047cd317603268c9410f62be9cb4
Author: Peter Zick <peterx.zick@intel.com>
Date:   Fri May 27 09:24:05 2011 -0700

    Changes to psb_powermgmt.c added to support the Moorestown configuration of the graphics and display islands power gating.

commit d631df0a967b002114ae0da22c885d97b24451fe
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Wed May 25 12:52:32 2011 -0700

    Set the display buffer DMA delay offset to 18ms. This is optimized for QT/MEEGO-UX.

commit f85694cb7d2a8d9d6e06857359a173af43639170
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Fri May 20 16:04:58 2011 -0700

    Use msec_to_jiffies() to insure an 11ms delay for the Display Buffer DMA timer.

commit 56c41edf7ee26b2f4f4aeb48b869e781253f149d
Author: Li Zeng <li.zeng@intel.com>
Date:   Thu May 12 13:16:57 2011 +0800

    ved: Decode hw sequence value is initilise to 1

    BZ: 1848

    After reboot, Decode hw sequence and sw sequence are both 0, so sync buffer always success even if it is not really ready.

    HW sequence value is initilise to 1 to avoid such issue

    Change-Id: I8886a67d70b412e147e3b99453442bf57490dc7d
Signed-off-by: Li Zeng <li.zeng@intel.com>
commit d705c82d06bee78d767379bdf3913eaabdfc6725
Author: Austin Yuan <shengquan.yuan@gmail.com>
Date:   Tue May 17 13:27:52 2011 +0800

    Video: optimized udelay usage

    1) From Liu, Haiyang: there is a call path psb_setup_fw() -> psb_wait_for_register()
    -> udelay(1000), which is not C0 friendly, reduce it to 1
    2) export three runtime options for further optimization/tuning
    -Export option "cpu_relax" to replace all "udelay" to "cpu_relax" at runtime
    -Export option "udelay_multiplier" to multiple the udealy usec with a value (increase)
    -Export option "udelay_divider" to divide the udelay usec with a value (decrease)

Signed-off-by: Austin Yuan <shengquan.yuan@gmail.com>
commit 09c31a9d4a4fb604ad7b5e798765bf70c5960bc7
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Wed May 11 13:19:43 2011 -0700

    Update the delay for DMA'ing the display buffer from VSync to 11ms (from 15ms). This is to account for the display frequency change of 48.8hz to 60hz.

commit 1ee4119468c1949cb6fbf931c5bdc24c83a5ba4d
Author: Ren, Zhaohan <zhaohan.ren@intel.com>
Date:   Wed May 11 15:56:48 2011 +0800

    Update psb_drm.h

commit 0e03d0f66fcec154a24b65e25726e13052d3fe4f
Author: Elaine Wang <elaine.wang@intel.com>
Date:   Wed May 4 15:42:29 2011 +0800

    Video:Fix Topaz D0i3 hang issue.

    BZ: 1478

    After enalbe Topaz D0i3 manually by "echo 0x2 > /sys/module/medfield_gfx/parameters/topaz_pmpolicy", video encoding performance is very low and the en
    coded clip is corruptted. See error message "TOPAZ timeout (probable lockup) detected" in terminal.

    This patch fix several potential problems in Topaz save and restore MTX state functions. Save the content of Topaz communication registers before power down Topaz and restore it after resume. Before power down Topaz, poll MMU control register until make sure there is no pending memory request. Reset MVEA twice according to IMG's advice. After transfer firmware to Topaz, kick NULL command to Topaz core 0 and core 1 and wait for its completion. If polling the writeback of NULL commands times out, read back 4 words from command FIFO to recover the state of it.

    Inserting NULL commands would cause extra delay of resuming Topaz and reading back 4 words from command FIFO doesn't guarantee successfuly recovery everytime, but it makes video encoding much more stable while enter and exit D0i3. It will be removed after IMG provide a total fix in Topaz firmware.

Signed-off-by: Elaine Wang <elaine.wang@intel.com>
commit 75a8b0604ff47effc895a5279965c2b5fc06a6db
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu May 5 09:09:17 2011 -0700

    Driver Package release 0043

commit 813601f6e4561dcea1bf914f02917b5e4ff57842
Author: Ren Zhaohan <zhaohan.ren@intel.com>
Date:   Thu Apr 28 09:42:53 2011 -0400

    GFX: Removed buffer 4 bytes alignment

    This restriction isn't needed.  This will allow creating buffer of any size.

commit 97f81d82513bda7f05593dd900ef009b4afbd8dd
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Tue May 3 14:06:11 2011 -0700

    GFX: add platform detect support

    refactor the code that checking MM system and Oaktrail platform
    put the dmi match code in psb_platform_detect(), add helper macros
    like IS_MRST_MM and IS_OAKTRAIL

Signed-off-by: Li Peng <peng.li@intel.com>
commit 1017a004a954a3a416a0e39d7466ed7c4443f01b
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Tue May 3 13:56:09 2011 -0700

    GFX: use raw_edid on mrst tablet

    currently the modeline used on mrst tablet is retrieved from GCT
    table in which the vertical refresh rate is about 49 HZ, but it isn't
    seem to be the best modeline because the EDID probed from LVDS panel
    recommending 60 HZ vrefresh rate.

    Also the h/w design on mrst tablet requires i2c0 as the channel for
    EDID probe, fixing this by adding DMI_MATCH code for mrst tablet.

    Another issue is that the EDID checksum on mrst tablet is bad, which block
    driver doing further modeline parse, this maybe a problem of LVDS panel,
    add workaround to use raw_edid on mrst tablet.

Signed-off-by: Li Peng <peng.li@intel.com>
commit 02968b64eba3ce5ac3c6a9d2bc5de3ae93814d45
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 20 17:01:53 2011 -0700

    GFX: Graphics Driver build release 5.3.0.0042

    Weekly Graphics driver release.
    Please use usermode package 0042 with this build.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 1f64690d7a4e0d4699a3db5d587e5d37e2c70772
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 20 14:33:06 2011 -0700

    GFX-Display: Enabled S0i3 for TMD panel.

    Now the system could enter and exit S0i3 for several times, with TMD/TPO panel
    attached on MDFLD, by the steps:
    1. Enable S0i3:
       a) echo 12000 > /proc/sys/vm/dirty_writeback_centisecs
       b) echo s0i3 > /sys/module/mid_pmu/parameters/s0ix
       c) echo 1 >/sys/devices/platform/max3110/adaptive
    2. xset dpms force off (or "xset s $TIMEOUT $INTERVAL")

    Also fixed the "Fabrice Error" issue when in S0i3 state.

Signed-off-by: Austin Hu <austin.hu@intel.com>
commit 77c3db295d9977b37c9cc4804b39d311ee074eb2
Author: Yu(Alex) Dai <yu.dai@intel.com>
Date:   Mon Mar 21 12:09:57 2011 -0700

    GFX: Fix memory release issue when X is crashed.

    This is an improvement for previous Fix.
    Now we add 3-level sanity check for PVRDeviceNode, BMContext and BMHeap.

Signed-off-by: Yu(Alex) Dai <yu.dai@intel.com>
commit 2fd2837ee86bd4edf5b3a27803adaa8bbc928fa5
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Tue Apr 5 14:39:34 2011 -0700

    GFX: Removed SUPPORT_EGL_EXTENSIONS

    Removing Some EGL Extension support.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit a0588a08a98795698b9ecc3e52b5429ec04fdacf
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 20 15:35:55 2011 -0700

    GFX: Cleanup video codying style

    Cleaning up Video driver coding style to match OpenSource
    Coding style.

Signed-off-by: Austin Yuan <shengquan.yuan@gmail.com>
commit 465cad2312c487a284e1689f6533813dafc72048
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Sun Apr 10 12:49:06 2011 -0700

    GFX: Fix tearing issue on Moorestown (Bugzilla 5503)

    Fix tearing on Moorestown due to race condition of Display moving
    buffer to screen on vysnc and driver swapping buffer on vsync.
    This is fixed here by using a timer to delay the driver flipping
    the display buffer. This change is made to not effect Medfield.

Signed-off-by: Daemon Anastas <daemonx.g.anastas@intel.com>
commit 801029054b4de50d58c4b17abfc68fb270c5574d
Author: Elaine Wang <elaine.wang@intel.com>
Date:   Wed Apr 13 15:23:56 2011 +0800

    GFX: Fix device firmware loading issue

    Fix a code defect that cause loading device firmware repeatedly
    in different video encoding sessions.

    Use Topaz context handle instead of variable topaz_fw_loaded to check
    if any video encoding process is running. When driver removes Topaz
    context, mark current MTX data as invalid to prohibit retoring MTX
    data wrongly at the beginning of next encoding session.

Signed-off-by: Elaine Wang <elaine.wang@intel.com>
commit ba38a2fed5bfa6ab988e83f8632ba4dee6eb76c2
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 13 14:34:59 2011 -0700

    GFX: Fix to avoid infinite loop in ospm_power_island_up/down.

    - Removed redundant code to power on/off GL3 (PSB_PWRGT_GFX_MASK_B0)
    - Added counters with debug prints to detect infinite loops
    - Added code to handle ISP on/off to be used by camera driver.
    - invalidate GL3 before suspend.
    - Add in OSPM_ISP_ISLAND check in ospm_power_island_up.

Signed-off-by: Rajesh Poornachandran <rajesh.poornachandran@intel.com>
commit 45e5aa0e53c403df69d4ef6de7927aa1433b7194
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Tue May 3 15:40:04 2011 -0700

    kernel rebase kernel-adaptation-mrst-2.6.37.6-38.2

commit d099ff36cb3385cd139e0ba5882128b68df67c5a
Author: Ren Zhaohan <zhaohan.ren@intel.com>
Date:   Thu Apr 28 09:42:53 2011 -0400

    Removed buffer 4 bytes alignment restriction to allow creating buffer of any size.

commit aa1ef8d15b18c0175dc0564601e842e682d5e130
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Fri Apr 22 11:24:37 2011 -0700

    GFX: Read EDID from i2c Adaptor #0 for MM

    MM Systems have EDID hooked up to i2c adaptor 0.
    Detect the MM system and read the EDID.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 0954d9c2eaf4f1d581a13e37ac2f3353c703d1d0
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 20 17:01:53 2011 -0700

    driver release 0042

commit 993db7289b98c5a055ff1f3d3c18d0e3d3b27721
Author: Austin Hu <austin.hu@intel.com>
Date:   Mon Apr 18 17:16:23 2011 +0800

    GFX-Display: Enabled D0i3 for the Display sub-system of Acer Tablet.

    Enable it by checking the current DC status in run-time runtime_suspend()/runtime_idle()
    callbacks, rather than checking DSR status which isn't supported by Acer Tablet's LVDS panel.

    Enable/Disable run-time PM with pm_runtime_put_noidle()/pm_runtime_get_noresume(), according
    to the common run-time PM changes since kernel 37.

    And here is the /sys/kernel/debug/mrst_pmu diff before and after DPMS off:

    Before:
        GFX: [BLOCKS s0i3]
        0000:00:02.0 8086/4102 pvrsrvkm                     PCI-D0   D0 10 0 0 6 0

    After:
        GFX:
        0000:00:02.0 8086/4102 pvrsrvkm                     PCI-D3hot D0 10 0 0 8 0

Signed-off-by: Austin Hu <austin.hu@intel.com>
commit df8c26f576b0fbdef4e5be7540ca38475c4eeee2
Author: Austin Yuan <shengquan.yuan@gmail.com>
Date:   Fri Apr 15 10:27:56 2011 +0800

    Cleanup video codying style

Signed-off-by: Austin Yuan <shengquan.yuan@gmail.com>
commit 1b0ce19f3ad640e10ec5e95bbbcb690ac40aeba4
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Sun Apr 10 12:49:06 2011 -0700

    GFX: Fix tearing issue on Moorestown (Bugzilla 5503)

    Fix tearing on Moorestown due to race condition of Display moving
    buffer to screen on vysnc and driver swapping buffer on vsync.
    This is fixed here by using a timer to delay the driver flipping
    the display buffer. This change is made to not effect Medfield.

Signed-off-by: Daemon Anastas <daemonx.g.anastas@intel.com>
commit 3efd32effa12928feb16eb5641262e5b175ac763
Author: Elaine Wang <elaine.wang@intel.com>
Date:   Wed Apr 13 15:23:56 2011 +0800

    GFX: Fix device firmware loading issue

    Fix a code defect that cause loading device firmware repeatedly
    in different video encoding sessions.

    Use Topaz context handle instead of variable topaz_fw_loaded to check
    if any video encoding process is running. When driver removes Topaz
    context, mark current MTX data as invalid to prohibit retoring MTX
    data wrongly at the beginning of next encoding session.

Signed-off-by: Elaine Wang <elaine.wang@intel.com>
commit bf9cf397c15cdefb37e5d19dc04b194c77c5909e
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Tue Apr 5 14:39:34 2011 -0700

    GFX: Removed SUPPORT_EGL_EXTENSIONS

    Removing Some EGL Extension support.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 1e90ac03aa57a1b6a2dcf3fb2d958150f5223de0
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 13 14:34:59 2011 -0700

    GFX: Fix to avoid infinite loop in ospm_power_island_up/down.

    - Removed redundant code to power on/off GL3 (PSB_PWRGT_GFX_MASK_B0)
    - Added counters with debug prints to detect infinite loops
    - Added code to handle ISP on/off to be used by camera driver.
    - invalidate GL3 before suspend.
    - Add in OSPM_ISP_ISLAND check in ospm_power_island_up.

Signed-off-by: Rajesh Poornachandran <rajesh.poornachandran@intel.com>
commit efe1620f8beb9e7c3c9b2c22792c2fc891fbbf3c
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Apr 14 11:24:46 2011 -0700

    Finally rebase to kernel-adaptation-mrst-2.6.37.6-26.1

commit 6ce9100dfde3e3e68764a5ccba9c2bbb590aede7
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Sun Apr 10 12:49:06 2011 -0700

    GFX: Fix tearing issue on Moorestown (Bugzilla 5503)

    Fix tearing on Moorestown due to race condition of Display moving
    buffer to screen on vysnc and driver swapping buffer on vsync.
    This is fixed here by using a timer to delay the driver flipping
    the display buffer. This change is made to not effect Medfield.

Signed-off-by: Daemon Anastas <daemonx.g.anastas@intel.com>
commit b0a6a0a3cd76de8b32dcc341b36ad220a37d8498
Author: Elaine Wang <elaine.wang@intel.com>
Date:   Wed Apr 13 15:23:56 2011 +0800

    GFX: Fix device firmware loading issue

    Fix a code defect that cause loading device firmware repeatedly
    in different video encoding sessions.

    Use Topaz context handle instead of variable topaz_fw_loaded to check
    if any video encoding process is running. When driver removes Topaz
    context, mark current MTX data as invalid to prohibit retoring MTX
    data wrongly at the beginning of next encoding session.

Signed-off-by: Elaine Wang <elaine.wang@intel.com>
commit f5541df0bf689ac4488b2b2ab5cfb18120023fd5
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Tue Apr 5 14:39:34 2011 -0700

    GFX: Removed SUPPORT_EGL_EXTENSIONS

    Removing Some EGL Extension support.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 5fb7d6107bf4a2b3903d45e7431fbe7b5c242d50
Author: Li Peng <peng.li@intel.com>
Date:   Thu Mar 31 11:22:33 2011 +0800

    mrst gfx: Oaktrail HDMI enabling patch

    [v3] more bugfixes in mode setting test
    [v2] adding audio support.
    [v1] video and i2c implementation.

Signed-off-by: Li Peng <peng.li@intel.com>
Signed-off-by: Li Peng <peng.li@linux.intel.com>
commit 38d8c9c05c5477d907f9a8f1b6f9dfe615d4b58f
Author: Li Peng <peng.li@intel.com>
Date:   Thu Mar 31 11:16:47 2011 +0800

    mrst gfx: change pipe number for oaktrail

    oaktrail platform (a variant of mrst) has two pipes, change
    pipe number to two.

Signed-off-by: Li Peng <peng.li@intel.com>
Signed-off-by: Li Peng <peng.li@linux.intel.com>
commit b88f9845e65b9dd0f2f7450795e1085918d2ade5
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 13 14:34:59 2011 -0700

    GFX: Fix to avoid infinite loop in ospm_power_island_up/down.

    - Removed redundant code to power on/off GL3 (PSB_PWRGT_GFX_MASK_B0)
    - Added counters with debug prints to detect infinite loops
    - Added code to handle ISP on/off to be used by camera driver.
    - invalidate GL3 before suspend.
    - Add in OSPM_ISP_ISLAND check in ospm_power_island_up.

Signed-off-by: Rajesh Poornachandran <rajesh.poornachandran@intel.com>
commit fa347620e74ec7aa76e96506514c51ec23ef7cfd
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 13 16:34:21 2011 -0700

    rebase kernel-adaptation-mrst-2.6.37.6-26.1

commit fe87b34dd827d2970dc0bb5e0eaf5b103ae9ca02
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Sun Apr 10 12:49:06 2011 -0700

    GFX: Fix tearing issue on Moorestown (Bugzilla 5503)

    Fix tearing on Moorestown due to race condition of Display moving
    buffer to screen on vysnc and driver swapping buffer on vsync.
    This is fixed here by using a timer to delay the driver flipping
    the display buffer. This change is made to not effect Medfield.

Signed-off-by: Daemon Anastas <daemonx.g.anastas@intel.com>
commit 5f44890f95b1e28e441c7c7963e6706e7f11a881
Author: Elaine Wang <elaine.wang@intel.com>
Date:   Wed Apr 13 15:23:56 2011 +0800

    GFX: Fix device firmware loading issue

    Fix a code defect that cause loading device firmware repeatedly
    in different video encoding sessions.

    Use Topaz context handle instead of variable topaz_fw_loaded to check
    if any video encoding process is running. When driver removes Topaz
    context, mark current MTX data as invalid to prohibit retoring MTX
    data wrongly at the beginning of next encoding session.

Signed-off-by: Elaine Wang <elaine.wang@intel.com>
commit 83429d2111104b378299458df9e24d373aeb0489
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Tue Apr 5 14:39:34 2011 -0700

    GFX: Removed SUPPORT_EGL_EXTENSIONS

    Removing Some EGL Extension support.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 65b6c93017bf226f79be269d4847a509de7ed055
Author: Li Peng <peng.li@intel.com>
Date:   Thu Mar 31 11:22:33 2011 +0800

    mrst gfx: Oaktrail HDMI enabling patch

    [v3] more bugfixes in mode setting test
    [v2] adding audio support.
    [v1] video and i2c implementation.

Signed-off-by: Li Peng <peng.li@intel.com>
Signed-off-by: Li Peng <peng.li@linux.intel.com>
commit dd770ce3d548ae3c463ca8411e59a3de37796017
Author: Li Peng <peng.li@intel.com>
Date:   Thu Mar 31 11:16:47 2011 +0800

    mrst gfx: change pipe number for oaktrail

    oaktrail platform (a variant of mrst) has two pipes, change
    pipe number to two.

Signed-off-by: Li Peng <peng.li@intel.com>
Signed-off-by: Li Peng <peng.li@linux.intel.com>
commit 4f213a9d02f689d9fe00102b6db71f8ac994a8b5
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 13 14:34:59 2011 -0700

    GFX: Fix to avoid infinite loop in ospm_power_island_up/down.

    - Removed redundant code to power on/off GL3 (PSB_PWRGT_GFX_MASK_B0)
    - Added counters with debug prints to detect infinite loops
    - Added code to handle ISP on/off to be used by camera driver.
    - invalidate GL3 before suspend.
    - Add in OSPM_ISP_ISLAND check in ospm_power_island_up.

Signed-off-by: Rajesh Poornachandran <rajesh.poornachandran@intel.com>
commit cc5b6236d07d1ffd5eb9202625baad9d1d0f4247
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Apr 13 15:46:21 2011 -0700

    git rebase kernel-adaptation-mrst-2.6.37.6-26.1

commit 56486202dfc76a2544a52bcf53d936824100d68b
Author: Daemon Anastas <daemonx.g.anastas@intel.com>
Date:   Tue Apr 12 19:07:24 2011 -0700

    check a spinlock and timer is not pending before setting timer (bugzilla 5503)

commit 2a6398ae1f523df0ba99c1dcafdd7a8a201d515a
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Apr 7 17:27:17 2011 -0700

    fix a typo

commit 063f2d34545728e7fc0df8e9b35217d94270bb1d
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Apr 7 16:43:19 2011 -0700

    GFX: Fix OSPM__ALL_ISLAND define

    OSPM_ALL_ISLAND is defined as 0x2f it needs to be 0x3f

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit a022158016906934e28fc5e43cab076bfc040e6c
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Apr 7 11:06:31 2011 -0700

    GFX: Fix to avoid infinite loop in ospm_power_island_up/down.

    - Removed redundant code to power on/off GL3 (PSB_PWRGT_GFX_MASK_B0)
    - Added counters with debug prints to detect infinite loops
    - Added code to handle ISP on/off to be used by camera driver.
    - invalidate GL3 before suspend.
    - Add in OSPM_ISP_ISLAND check in ospm_power_island_up.

Signed-off-by: Rajesh Poornachandran <rajesh.poornachandran@intel.com>
commit c929a97c9e94eb687f015936f7309fdbeb015e8d
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Tue Apr 5 14:39:34 2011 -0700

    GFX: Removed SUPPORT_EGL_EXTENSIONS

    Removing Some EGL Extension support.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 39e1a780478c305e511ba6d1d51b7a29f9a0c7fb
Author: Li Peng <peng.li@intel.com>
Date:   Thu Mar 31 11:22:33 2011 +0800

    mrst gfx: Oaktrail HDMI enabling patch

    [v3] more bugfixes in mode setting test
    [v2] adding audio support.
    [v1] video and i2c implementation.

Signed-off-by: Li Peng <peng.li@intel.com>
Signed-off-by: Li Peng <peng.li@linux.intel.com>
commit 524e0ef2b155c944eb911b72589433377175c09c
Author: Li Peng <peng.li@intel.com>
Date:   Thu Mar 31 11:16:47 2011 +0800

    mrst gfx: change pipe number for oaktrail

    oaktrail platform (a variant of mrst) has two pipes, change
    pipe number to two.

Signed-off-by: Li Peng <peng.li@intel.com>
Signed-off-by: Li Peng <peng.li@linux.intel.com>
commit 822f7c7b0906ac49cbc975dda57ed378aa085741
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Mar 31 12:24:58 2011 -0700

    GFX: Graphics Driver build release 5.3.0.0041

    Weekly Graphics driver release.
    Please use usermode package 0041 with this build.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit f2e96e8f02812a0db19aadb8507f655a9948ac35
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Mar 31 12:14:22 2011 -0700

    GFX: Optimize and Disable GL3

    Use the bottom page of KERN_DATA_HEAP for GL3_USSE_WR_ADDR
    Disable GL3.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit dea7a3147923567ffe8bb9ffa5345b995ca5fa85
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Thu Mar 31 11:56:29 2011 -0700

    GFX: Fix for Runtime PM

    Runtime PM counters were not correctly incremneted/decremented
    since we were always decrementing even in fail condition but not
    incrementing in failed condition.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 80bdde90d17087d071d4d33111f11cd7f22b8fc4
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Mar 30 17:10:55 2011 -0700

    GFX: Add PMIC Backlight controls

    On Some morrestown platform the backlight is attached to PMIC.  This patch will...

    1. Enable Brighness level adjustment through PMIC Backlight controller
    2. Turn off Backlight completely when LVDS panel is off

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit 7399372ed507dfb318debe28a5644b4ee026f020
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Mar 30 17:10:15 2011 -0700

    revert PMIC backlight source

commit 454de637c7019a24da0d03efd169b0b9b0b70940
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Mon Mar 28 15:10:59 2011 -0700

    GFX: Add PMIC Backlight controls

    On Some morrestown platform the backlight is attached to PMIC.  This patch will...

    1. Enable Brighness level adjustment through PMIC Backlight controller
    2. Turn off Backlight completely when LVDS panel is off

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit cb94ee7a31a2a276c120b6edea9f01fa7d1bdb32
Author: Austin Hu <austin.hu@intel.com>
Date:   Thu Mar 24 15:43:00 2011 +0800

    GFX: Fixed a memory leak issue in the DRM_PSB_GETPAGEADDRS IOCTL.

    Fix Memory leak in TTM-GLUE.

Signed-off-by: Austin Hu <austin.hu@intel.com>
commit 9397a7c2e7d74e40c9a17bcf8989782b2181ce05
Author: Austin Yuan <shengquan.yuan@gmail.com>
Date:   Thu Mar 24 13:51:18 2011 +0800

    GFX: ospm_power_island_up/down: use loop counter to avoid infinite dead loop

    Attemp to fix 3577740:UI freeze during video playback due to events/0 over CPU consumption

    The rootcause is ospm_power_island_up/down run into dead loop

Signed-off-by: Austin Yuan <shengquan.yuan@gmail.com>
commit c0a076ee8d51e0e28b651801f45e62f563264769
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Wed Mar 23 14:32:10 2011 -0700

    GFX: Graphics Driver build release 5.3.0.0040

    Weekly Graphics driver release.
    Please use usermode package 0040 with this build.

Signed-off-by: Hitesh K. Patel <hitesh.k.patel@intel.com>
commit e9687aef40806d9577559ee0f2519a5a7e4f7f0a
Author: Hitesh K. Patel <hitesh.k.patel@intel.com>
Date:   Mon Mar 28 14:55:47 2011 -0700

    kernel rebase 2.6.37.57.1

commit cdb8d38531e2fbfb36762dd4cfa25516bd37e75e
Author: Yu(Alex) Dai <yu.dai@intel.com>
Date:   Thu Mar 3 21:30:46 2011 +0800

    Enlarge GENERAL_MAPPING heap to make sure more apps can run on SGX535 platform simultaneously.

    The GENERAL_MAPPING heap is created as shared heap for multi-contexts
    to fix one HW issue (BRN_23410). The heap size is set to 128M, which
    is not enough for high memory usage under MeeGo Tablet 1280x600 mode.
    Now set it to 512M to satisfy UI memory request.

Signed-off-by: Yu(Alex) Dai <yu.dai@intel.com>
commit b7561fedff1a11f785d2e2e2abbeeb3577f6cffb
Author: Jackie Li <yaodong.li@intel.com>
Date:   Thu Mar 3 21:30:08 2011 +0800

    GFX-Display: Fixed glsync tearing issue on MIPI panel.

    Tearing happens while running glsync -s b on both MIPI panel with vsync enabled.
    The root cause of this issue is that 3D blit happens during write_mem_start command transmission.

    Add a fixing to wait for DBI FIFO empty before schedule 3D blit to system frame buffer.
    TE interrupt of second MIPI panel was enabled since we need to send out write_mem_start command only when TE interrupt happens.

    Known issue:
    In dual MIPI clone mode, two MIPI panels share the same system frame buffer and TE interrupts may NOT happen at the same time,
    so if one of the TE interrupt handler woke up 3D blit to frame buffer, there would be tearing on the other MIPI panel
    if it is sending write_mem_start command

Signed-off-by: Jackie Li <yaodong.li@intel.com>
commit 9ef6a38fe330be33f74983b63c406a2fca52bdbc
Author: Justin Dou <Justin.Dou@intel.com>
Date:   Thu Mar 3 21:14:54 2011 +0800

    Added the kernel-mid.config for mrst kernel build and updated our gfx driver to 0038 version

    The kernel-mid.config is now aligned with configs/kernel-adaptation-mrst.config which was used for handset image build.

Signed-off-by: Justin Dou <Justin.Dou@intel.com>
commit f8aadafe3d6f4c4db5a5cb698b7df5e957c6517a
Author: Justin Dou <Justin.Dou@intel.com>
Date:   Thu Mar 3 20:15:22 2011 +0800

    Create the MRST kernel branch with kernel-adaptation-mrst-2.6.37-13.2.src.rpm

    This is the up-to-date kernel from http://download.meego.com/live/Trunk/standard/src/ which integrated our 0037 gfx driver.

Signed-off-by: Justin Dou <Justin.Dou@intel.com>
283 files changed:
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/mrst/.gitignore [new file with mode: 0644]
drivers/staging/mrst/Kconfig [new file with mode: 0644]
drivers/staging/mrst/Makefile [new file with mode: 0644]
drivers/staging/mrst/README [new file with mode: 0644]
drivers/staging/mrst/bc_video/bufferclass_video.c [new file with mode: 0644]
drivers/staging/mrst/bc_video/bufferclass_video.h [new file with mode: 0644]
drivers/staging/mrst/bc_video/bufferclass_video_linux.c [new file with mode: 0644]
drivers/staging/mrst/bc_video/bufferclass_video_linux.h [new file with mode: 0644]
drivers/staging/mrst/drv/displays/hdmi.h [new file with mode: 0644]
drivers/staging/mrst/drv/displays/tmd_vid.h [new file with mode: 0644]
drivers/staging/mrst/drv/displays/tpo_cmd.h [new file with mode: 0644]
drivers/staging/mrst/drv/displays/tpo_vid.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_dbi.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_dbi.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_dpi.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_dpi.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_output.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_output.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_gl3.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_gl3.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_hdcp.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_hdcp_if.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_hdcp_reg.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_hdmi_audio.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_hdmi_audio_if.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_intel_hdcp.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_msic.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_msic.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_output.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_output.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_bl.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_dpst.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_dpst.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_drm.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_drv.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_drv.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_fb.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_fb.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_gtt.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_gtt.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_hotplug.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_hotplug.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_display.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_display.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_drv.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_hdmi.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_hdmi.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_hdmi_edid.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_hdmi_i2c.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_hdmi_i2c.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_hdmi_reg.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_intel_reg.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_irq.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_irq.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_page_flip.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_page_flip.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_powermgmt.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_powermgmt.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_pvr_glue.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_pvr_glue.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_reg.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_reset.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_schedule.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_schedule.h [new file with mode: 0644]
drivers/staging/mrst/drv/psb_sgx.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_socket.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_umevents.c [new file with mode: 0644]
drivers/staging/mrst/drv/psb_umevents.h [new file with mode: 0644]
drivers/staging/mrst/drv/tc35876x-dsi-lvds.c [new file with mode: 0644]
drivers/staging/mrst/drv/tc35876x-dsi-lvds.h [new file with mode: 0644]
drivers/staging/mrst/drv/tmd_vid.c [new file with mode: 0644]
drivers/staging/mrst/drv/tpo_cmd.c [new file with mode: 0644]
drivers/staging/mrst/drv/tpo_vid.c [new file with mode: 0644]
drivers/staging/mrst/imgv/msvdx_power.c [new file with mode: 0644]
drivers/staging/mrst/imgv/msvdx_power.h [new file with mode: 0644]
drivers/staging/mrst/imgv/pnw_topaz.c [new file with mode: 0644]
drivers/staging/mrst/imgv/pnw_topaz.h [new file with mode: 0644]
drivers/staging/mrst/imgv/pnw_topaz_hw_reg.h [new file with mode: 0644]
drivers/staging/mrst/imgv/pnw_topazinit.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_buffer.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_fence.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_mmu.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_msvdx.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_msvdx.h [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_msvdxinit.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_fence.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_fence_api.h [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_fence_driver.h [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_fence_user.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_fence_user.h [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_glue.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_placement_user.c [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_placement_user.h [new file with mode: 0644]
drivers/staging/mrst/imgv/psb_ttm_userobj_api.h [new file with mode: 0644]
drivers/staging/mrst/imgv/topaz_power.c [new file with mode: 0644]
drivers/staging/mrst/imgv/topaz_power.h [new file with mode: 0644]
drivers/staging/mrst/medfield/Makefile [new file with mode: 0644]
drivers/staging/mrst/pvr/COPYING [new file with mode: 0644]
drivers/staging/mrst/pvr/INSTALL [new file with mode: 0644]
drivers/staging/mrst/pvr/README [new file with mode: 0644]
drivers/staging/mrst/pvr/eurasiacon/.gitignore [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/dbgdrvif.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/img_defs.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/img_types.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/ioctldef.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/pdumpdefs.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/pvr_debug.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/pvrmodule.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/pvrversion.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/regpaths.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/services.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/servicesext.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/sgx_options.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/sgxapi_km.h [new file with mode: 0644]
drivers/staging/mrst/pvr/include4/sgxscript.h [new file with mode: 0644]
drivers/staging/mrst/pvr/pvr_debugfs.c [new file with mode: 0644]
drivers/staging/mrst/pvr/pvr_debugfs.h [new file with mode: 0644]
drivers/staging/mrst/pvr/pvr_trace_cmd.c [new file with mode: 0644]
drivers/staging/mrst/pvr/pvr_trace_cmd.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/.gitignore [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/makefile.linux.common [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb_displayclass.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb_linux.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/env/linux-intel/pvr_drm_shared.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/env/linux/pvr_drm_shared.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/kernelbuffer.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/kerneldisplay.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/pdump.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/pvr_bridge.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/pvr_bridge_km.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/pvrmmap.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/pvrsrv_errors.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/servicesint.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/sgx_bridge.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/sgx_mkif_km.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/include/sgxinfo.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/bridged/.gitignore [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_support.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_support.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/.gitignore [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/buffer_manager.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/deviceclass.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/deviceid.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/devicemem.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/handle.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/hash.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/lists.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/mem.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/mem_debug.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/metrics.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/osfunc_common.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/pdump_common.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/perproc.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/power.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/pvrsrv.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/queue.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/ra.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/common/resman.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/.gitignore [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/mmu.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/mmu.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/pb.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxconfig.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxinfokm.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxinit.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxkick.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxpower.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxreset.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxtransfer.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxutils.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxutils.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/env_data.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/env_perproc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/event.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/event.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/linkage.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/lock.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mm.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mm.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mmap.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mmap.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/module.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mutils.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mutils.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/osfunc.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/osperproc.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pdump.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/private_data.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/proc.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/proc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_bridge_k.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_debug.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_drm.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_drm.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/.gitignore [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/env_data.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/env_perproc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/event.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/event.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/linkage.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/lock.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/mmap.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/mmap.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/module.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutex.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutex.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutils.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutils.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/osfunc.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/osperproc.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/ossync.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/pdump.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/private_data.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/proc.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/proc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_bridge_k.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_debug.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_drm.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_drm.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgx535defs.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgx540defs.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxdefs.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxerrata.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxmmu.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/buffer_manager.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/device.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/handle.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/hash.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/lists.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/metrics.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/osfunc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/osperproc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/ossync.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/pdump_int.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/pdump_km.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/pdump_osfunc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/perproc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/power.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/queue.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/ra.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/resman.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/services_headers.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/srvkm/include/srvkm.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/include/syscommon.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/extsyscache.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/oemfuncs.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_export.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_export.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_import.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/sysconfig.c [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/sysconfig.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/sysinfo.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/syslocal.h [new file with mode: 0644]
drivers/staging/mrst/pvr/services4/system/unified/sysutils.c [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/client/linuxsrv.h [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv_ioctl.h [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/handle.c [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hotkey.c [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hotkey.h [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/ioctl.c [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/main.c [new file with mode: 0644]
drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common [new file with mode: 0644]
include/drm/drm_os_linux.h

index d0c8c0e..638f31a 100644 (file)
@@ -154,6 +154,8 @@ source "drivers/staging/ste_rmi4/Kconfig"
 
 source "drivers/staging/gma500/Kconfig"
 
+source "drivers/staging/mrst/Kconfig"
+
 source "drivers/staging/altera-stapl/Kconfig"
 
 source "drivers/staging/mei/Kconfig"
index 250fb24..f38c6c1 100644 (file)
@@ -69,6 +69,7 @@ obj-$(CONFIG_ALTERA_STAPL)    +=altera-stapl/
 obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217)      += cptm1217/
 obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)   += ste_rmi4/
 obj-$(CONFIG_DRM_PSB)          += gma500/
+obj-$(CONFIG_DRM_INTEL_MID)    += mrst/
 obj-$(CONFIG_INTEL_MEI)                += mei/
 obj-$(CONFIG_MFD_NVEC)         += nvec/
 obj-$(CONFIG_DRM_INTEL_MID)     += mrst/
diff --git a/drivers/staging/mrst/.gitignore b/drivers/staging/mrst/.gitignore
new file mode 100644 (file)
index 0000000..dc64e05
--- /dev/null
@@ -0,0 +1,3 @@
+# HACK: These are intermediate files in PVR driver build.
+*.medfield.c
+*.mrst.c
diff --git a/drivers/staging/mrst/Kconfig b/drivers/staging/mrst/Kconfig
new file mode 100644 (file)
index 0000000..8758ae8
--- /dev/null
@@ -0,0 +1,111 @@
+#
+# Drm device configuration
+#
+# This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+#
+
+config DRM_INTEL_MID
+       tristate "Intel Moorestown/Medfield (load along with IMG driver)"
+       depends on DRM && PCI
+       select FB_CFB_COPYAREA
+        select FB_CFB_FILLRECT
+        select FB_CFB_IMAGEBLIT
+        select DRM_KMS_HELPER
+        select DRM_TTM
+       help
+         xxxxxxxxxxxxxxxxxxxxxxxxxx
+
+choice 
+       prompt "Build IMG kernel service as "
+       depends on DRM_INTEL_MID
+       default DRM_MID_RELEASE
+
+config DRM_MID_RELEASE
+       bool "Release"
+       depends on DRM_INTEL_MID
+       help
+         Build IMG kernel services as release
+
+config DRM_MID_DEBUG
+       bool "Debug"
+       depends on DRM_INTEL_MID
+       help
+        Build IMG kernel services as debug     
+
+endchoice
+
+config DRM_MDFLD
+       tristate "Intel Medfield"
+        depends on DRM_INTEL_MID && PCI
+        select FB_CFB_COPYAREA
+        select FB_CFB_FILLRECT
+        select FB_CFB_IMAGEBLIT
+        select DRM_KMS_HELPER
+        help
+          Choose this option if you have a Medfield platform.
+          If M is selected the module will be called mid_gfx.
+
+config MDFLD_DSI_DSR
+       bool "Support DSI Fullscreen Display Self Refreshment "
+       depends on DRM_MDFLD && !MDFLD_DSI_DPU
+       default y
+       help
+         Choose this option if you have a Type1 MIPI panel.
+
+config MDFLD_DSI_DPU
+       bool "Support DSI Display Partial Update"
+       depends on DRM_MDFLD
+       default n
+       help
+         xxxxxx
+
+config MDFD_DUAL_MIPI
+        bool "SUPPORT_DUAL_MIPI_DISPLAYS"
+        depends on DRM_MDFLD
+        default n
+        help
+          xxxxxx
+
+config MDFD_HDMI
+        bool "SUPPORT_HDMI_DISPLAY"
+        depends on DRM_MDFLD
+        default n
+        help
+          xxxxxx
+
+config MDFD_GL3
+       bool "Enable GL3 Cache for GUNIT"
+       depends on DRM_MDFLD
+       default n
+       help
+         xxxxxx
+
+config PVR_TRACE_CMD
+       depends on DRM_INTEL_MID
+       bool "Enable GPU command tracing"
+       default n
+       help
+         This will enable a lightweight tracer of commands submitted
+         to the GPU.
+
+         Besides the command type the trace output will provide the
+         timestamp, id and name of the submitting process and a
+         a snapshots of the synchronization counters related to the
+         given command.
+
+         The trace can help for example in debugging dead-lock
+         situations caused by circular lock dependencies.
+
+config PVR_TRACE_CMD_BUF_SHIFT
+       int "Command tracing buf size"
+       range 1 10
+       default 3
+       depends on PVR_TRACE_CMD
+       help
+         Select the number of pages (as a power of 2) set aside for
+         the command trace buffer.
+         Examples:
+         1  -> 4kB
+         3  -> 32kB
+         10 -> 4MB
diff --git a/drivers/staging/mrst/Makefile b/drivers/staging/mrst/Makefile
new file mode 100644 (file)
index 0000000..f5af6a7
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_DRM_MDFLD)                += medfield/
+obj-$(CONFIG_DRM_MRST)         += moorestown/
diff --git a/drivers/staging/mrst/README b/drivers/staging/mrst/README
new file mode 100644 (file)
index 0000000..bbbbb33
--- /dev/null
@@ -0,0 +1,48 @@
+
+SOURCE
+
+This driver is a forward port of the Poulsbo/Langwell/Penwell SGX graphics and
+display controller drivers from 2.6.37 to 3.0-rc-something.
+
+The starting point was the meego-kernel-branch-mrst-k37 branch on [1]. The
+commits touching drivers/staging/mrst directory were exported to patches using:
+
+$ git format-patch -1000 meego-kernel-branch-mrst-k37 -- drivers/staging/mrst
+
+Note that the above filters out the changes outside drivers/staging/mrst.
+
+The patches were then applied on top of the MID repository [2]. Possibly due to
+rebases in the original tree [1] there were some conflicts that were
+resolved. In the end, this did not report any diff:
+
+$ git diff meego-kernel-branch-mrst-k37 -- drivers/staging/mrst
+
+After this, the build problems were fixed one by one.
+
+
+TODO
+
+* Make it work.
+
+* Continuous: Merge [2] (and thus Linus' tree) here as it is updated.
+
+* Review the hacked up quick fixes to build problems.
+
+* Possibly update the DDK version.
+
+* Merge the diverged and polished drivers/staging/gma500 back with this driver.
+
+* Finally: Backport the combined drivers and hardware adaptation to desired
+  kernel version.
+
+
+NOTES
+
+There is arch/x86/configs/medfield_pvr_defconfig known to work. It excludes the
+drivers/staging/gma500 driver as long as the drivers have not been merged.
+
+
+REFERENCES
+
+[1] git://gfx-build.fm.intel.com/kernel.git
+[2] git://git.kernel.org/pub/scm/linux/kernel/git/alan/linux-3.0-mid-ref.git
diff --git a/drivers/staging/mrst/bc_video/bufferclass_video.c b/drivers/staging/mrst/bc_video/bufferclass_video.c
new file mode 100644 (file)
index 0000000..707f851
--- /dev/null
@@ -0,0 +1,305 @@
+/***************************************************************************
+ *
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ******************************************************************************/
+
+#if defined(__linux__)
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+#include "bufferclass_video.h"
+#include "bufferclass_video_linux.h"
+
+#define VBUFFERCLASS_DEVICE_NAME "Video Bufferclass Device"
+#define CBUFFERCLASS_DEVICE_NAME "Camera Bufferclass Device"
+
+static void *gpvAnchorVideo[BC_VIDEO_DEVICE_MAX_ID];
+
+static void *gpcAnchor;
+static PFN_BC_GET_PVRJTABLE pfnGetPVRJTable = IMG_NULL;
+
+BC_VIDEO_DEVINFO *
+GetAnchorPtr(int id)
+{
+       BC_VIDEO_DEVINFO *AnchorPtr = NULL;
+       if (id < BC_VIDEO_DEVICE_MAX_ID)
+               AnchorPtr = gpvAnchorVideo[id];
+       else if (id == BC_CAMERA_DEVICEID)
+               AnchorPtr = gpcAnchor;
+       return AnchorPtr;
+}
+
+static void
+SetAnchorPtr(BC_VIDEO_DEVINFO * psDevInfo, int id)
+{
+       if (id < BC_VIDEO_DEVICE_MAX_ID)
+               gpvAnchorVideo[id] = (void *) psDevInfo;
+       else if (id == BC_CAMERA_DEVICEID)
+               gpcAnchor = (void *) psDevInfo;
+}
+
+static PVRSRV_ERROR
+OpenVBCDevice(IMG_UINT32 uDeviceID, IMG_HANDLE * phDevice)
+{
+       BC_VIDEO_DEVINFO *psDevInfo;
+       int id;
+       *phDevice = NULL;
+       for (id = 0; id < BC_VIDEO_DEVICE_MAX_ID; id++) {
+               psDevInfo = GetAnchorPtr(id);
+               if (psDevInfo != NULL && psDevInfo->ulDeviceID == uDeviceID) {
+                       *phDevice = (IMG_HANDLE) psDevInfo;
+                       break;
+               }
+       }
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR OpenCBCDevice(IMG_UINT32 uDeviceID, IMG_HANDLE *phDevice)
+{
+       BC_VIDEO_DEVINFO *psDevInfo;
+
+       UNREFERENCED_PARAMETER(uDeviceID);
+       psDevInfo = GetAnchorPtr(BC_CAMERA_DEVICEID);
+
+       *phDevice = (IMG_HANDLE)psDevInfo;
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+CloseBCDevice(IMG_UINT32 uDeviceID, IMG_HANDLE hDevice)
+{
+       UNREFERENCED_PARAMETER(uDeviceID);
+       UNREFERENCED_PARAMETER(hDevice);
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+GetBCBuffer(IMG_HANDLE hDevice,
+           IMG_UINT32 ui32BufferNumber,
+           PVRSRV_SYNC_DATA * psSyncData, IMG_HANDLE * phBuffer)
+{
+       BC_VIDEO_DEVINFO *psDevInfo;
+
+       if (!hDevice || !phBuffer) {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (BC_VIDEO_DEVINFO *) hDevice;
+
+       if (ui32BufferNumber < psDevInfo->sBufferInfo.ui32BufferCount) {
+               psDevInfo->psSystemBuffer[ui32BufferNumber].psSyncData = psSyncData;
+               *phBuffer = (IMG_HANDLE) & psDevInfo->psSystemBuffer[ui32BufferNumber];
+       } else {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+GetBCInfo(IMG_HANDLE hDevice, BUFFER_INFO * psBCInfo)
+{
+       BC_VIDEO_DEVINFO *psDevInfo;
+
+       if (!hDevice || !psBCInfo) {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (BC_VIDEO_DEVINFO *) hDevice;
+
+       *psBCInfo = psDevInfo->sBufferInfo;
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+GetBCBufferAddr(IMG_HANDLE hDevice,
+               IMG_HANDLE hBuffer,
+               IMG_SYS_PHYADDR ** ppsSysAddr,
+               IMG_UINT32 * pui32ByteSize,
+               IMG_VOID ** ppvCpuVAddr,
+               IMG_HANDLE * phOSMapInfo,
+               IMG_BOOL * pbIsContiguous, IMG_UINT32 * pui32TilingStride)
+{
+       BC_VIDEO_BUFFER *psBuffer;
+
+       UNREFERENCED_PARAMETER(pui32TilingStride);
+       if (!hDevice || !hBuffer || !ppsSysAddr || !pui32ByteSize) {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psBuffer = (BC_VIDEO_BUFFER *) hBuffer;
+
+       *ppvCpuVAddr = psBuffer->sCPUVAddr;
+
+       *phOSMapInfo = IMG_NULL;
+       *pui32ByteSize = (IMG_UINT32) psBuffer->ulSize;
+
+       *ppsSysAddr = psBuffer->psSysAddr;
+       *pbIsContiguous = psBuffer->is_conti_addr;
+
+       return (PVRSRV_OK);
+}
+
+
+BCE_ERROR
+BC_Video_Register(int id)
+{
+       BC_VIDEO_DEVINFO *psDevInfo;
+
+       psDevInfo = GetAnchorPtr(id);
+
+       if (psDevInfo == NULL) {
+               psDevInfo =
+                       (BC_VIDEO_DEVINFO *) BCAllocKernelMem(sizeof(BC_VIDEO_DEVINFO));
+
+               if (!psDevInfo) {
+                       return (BCE_ERROR_OUT_OF_MEMORY);
+               }
+
+               SetAnchorPtr((void *) psDevInfo, id);
+
+               psDevInfo->ulRefCount = 0;
+
+               if (BCOpenPVRServices(&psDevInfo->hPVRServices) != BCE_OK) {
+                       return (BCE_ERROR_INIT_FAILURE);
+               }
+               if (BCGetLibFuncAddr
+                   (psDevInfo->hPVRServices, "PVRGetBufferClassJTable",
+                    &pfnGetPVRJTable) != BCE_OK) {
+                       return (BCE_ERROR_INIT_FAILURE);
+               }
+
+               if (!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable)) {
+                       return (BCE_ERROR_INIT_FAILURE);
+               }
+
+               psDevInfo->ulNumBuffers = 0;
+
+               psDevInfo->sBufferInfo.pixelformat = PVRSRV_PIXEL_FORMAT_UNKNOWN;
+               psDevInfo->sBufferInfo.ui32Width = 0;
+               psDevInfo->sBufferInfo.ui32Height = 0;
+               psDevInfo->sBufferInfo.ui32ByteStride = 0;
+               psDevInfo->sBufferInfo.ui32BufferDeviceID = id;
+               psDevInfo->sBufferInfo.ui32Flags = 0;
+               psDevInfo->sBufferInfo.ui32BufferCount =
+                       (IMG_UINT32) psDevInfo->ulNumBuffers;
+
+               if (id < BC_VIDEO_DEVICE_MAX_ID) {
+                       strncpy(psDevInfo->sBufferInfo.szDeviceName,
+                               VBUFFERCLASS_DEVICE_NAME, MAX_BUFFER_DEVICE_NAME_SIZE);
+                       psDevInfo->sBCJTable.pfnOpenBCDevice = OpenVBCDevice;
+               } else if (id == BC_CAMERA_DEVICEID) {
+                       strncpy(psDevInfo->sBufferInfo.szDeviceName,
+                               CBUFFERCLASS_DEVICE_NAME, MAX_BUFFER_DEVICE_NAME_SIZE);
+                       psDevInfo->sBCJTable.pfnOpenBCDevice = OpenCBCDevice;
+               }
+
+               psDevInfo->sBCJTable.ui32TableSize =
+                       sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE);
+               psDevInfo->sBCJTable.pfnCloseBCDevice = CloseBCDevice;
+               psDevInfo->sBCJTable.pfnGetBCBuffer = GetBCBuffer;
+               psDevInfo->sBCJTable.pfnGetBCInfo = GetBCInfo;
+               psDevInfo->sBCJTable.pfnGetBufferAddr = GetBCBufferAddr;
+
+               if (psDevInfo->sPVRJTable.
+                   pfnPVRSRVRegisterBCDevice(&psDevInfo->sBCJTable,
+                                             &psDevInfo->ulDeviceID) != PVRSRV_OK) {
+                       return (BCE_ERROR_DEVICE_REGISTER_FAILED);
+               }
+       }
+
+       psDevInfo->ulRefCount++;
+
+       return (BCE_OK);
+}
+
+BCE_ERROR
+BC_Video_Unregister(int id)
+{
+       BC_VIDEO_DEVINFO *psDevInfo;
+
+       psDevInfo = GetAnchorPtr(id);
+
+       if (psDevInfo == NULL) {
+               return (BCE_ERROR_GENERIC);
+       }
+
+       psDevInfo->ulRefCount--;
+
+       if (psDevInfo->ulRefCount == 0) {
+               PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable = &psDevInfo->sPVRJTable;
+
+               if (psJTable->pfnPVRSRVRemoveBCDevice(psDevInfo->ulDeviceID) !=
+                   PVRSRV_OK) {
+                       return (BCE_ERROR_GENERIC);
+               }
+
+               if (BCClosePVRServices(psDevInfo->hPVRServices) != BCE_OK) {
+                       psDevInfo->hPVRServices = NULL;
+                       return (BCE_ERROR_GENERIC);
+               }
+
+               if (psDevInfo->psSystemBuffer) {
+                       BCFreeKernelMem(psDevInfo->psSystemBuffer);
+               }
+
+               BCFreeKernelMem(psDevInfo);
+
+               SetAnchorPtr(NULL, id);
+       }
+       return (BCE_OK);
+}
+
+BCE_ERROR
+BC_Video_Init(int id)
+{
+       BCE_ERROR eError;
+
+       eError = BC_Video_Register(id);
+       if (eError != BCE_OK) {
+               return eError;
+       }
+
+       return (BCE_OK);
+}
+
+BCE_ERROR
+BC_Video_Deinit(int id)
+{
+       BCE_ERROR eError;
+
+       BC_DestroyBuffers(id);
+
+       eError = BC_Video_Unregister(id);
+       if (eError != BCE_OK) {
+               return eError;
+       }
+
+       return (BCE_OK);
+}
diff --git a/drivers/staging/mrst/bc_video/bufferclass_video.h b/drivers/staging/mrst/bc_video/bufferclass_video.h
new file mode 100644 (file)
index 0000000..fcead60
--- /dev/null
@@ -0,0 +1,166 @@
+/**********************************************************************
+ *
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ******************************************************************************/
+
+#ifndef __BC_VIDEO_H__
+#define __BC_VIDEO_H__
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kernelbuffer.h"
+#include <kernel.h>
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+       enum BC_memory
+       {
+               BC_MEMORY_MMAP = 1,
+               BC_MEMORY_USERPTR = 2,
+       };
+
+       /*
+        * the following types are tested for fourcc in struct bc_buf_params_t
+        *   NV12
+        *   UYVY
+        *   RGB565 - not tested yet
+        *   YUYV
+        */
+       typedef struct bc_buf_params {
+               int count;            /*number of buffers, [in/out] */
+               int width;            /*buffer width in pixel, multiple of 8 or 32 */
+               int height;            /*buffer height in pixel */
+               int stride;
+               unsigned int fourcc;    /*buffer pixel format */
+               enum BC_memory type;
+       } bc_buf_params_t;
+
+       extern IMG_IMPORT IMG_BOOL
+       PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE * psJTable);
+
+#define BC_VIDEO_DEVICE_MAX_ID          5
+#define BC_CAMERA_DEVICEID              8
+
+       typedef void *BCE_HANDLE;
+
+       typedef enum tag_bce_bool {
+               BCE_FALSE = 0,
+               BCE_TRUE = 1,
+       } BCE_BOOL, *BCE_PBOOL;
+
+       typedef struct BC_VIDEO_BUFFER_TAG {
+               unsigned long ulSize;
+               BCE_HANDLE hMemHandle;
+
+               IMG_SYS_PHYADDR *psSysAddr;
+
+               IMG_CPU_VIRTADDR sCPUVAddr;
+               PVRSRV_SYNC_DATA *psSyncData;
+
+               struct BC_VIDEO_BUFFER_TAG *psNext;
+               int sBufferHandle;
+               IMG_BOOL is_conti_addr;
+       } BC_VIDEO_BUFFER;
+
+       typedef struct BC_VIDEO_DEVINFO_TAG {
+               IMG_UINT32 ulDeviceID;
+
+               BC_VIDEO_BUFFER *psSystemBuffer;
+
+               unsigned long ulNumBuffers;
+
+               PVRSRV_BC_BUFFER2SRV_KMJTABLE sPVRJTable;
+
+               PVRSRV_BC_SRV2BUFFER_KMJTABLE sBCJTable;
+
+               BCE_HANDLE hPVRServices;
+
+               unsigned long ulRefCount;
+
+               BUFFER_INFO sBufferInfo;
+               enum BC_memory buf_type;
+       } BC_VIDEO_DEVINFO;
+
+       typedef enum _BCE_ERROR_ {
+               BCE_OK = 0,
+               BCE_ERROR_GENERIC = 1,
+               BCE_ERROR_OUT_OF_MEMORY = 2,
+               BCE_ERROR_TOO_FEW_BUFFERS = 3,
+               BCE_ERROR_INVALID_PARAMS = 4,
+               BCE_ERROR_INIT_FAILURE = 5,
+               BCE_ERROR_CANT_REGISTER_CALLBACK = 6,
+               BCE_ERROR_INVALID_DEVICE = 7,
+               BCE_ERROR_DEVICE_REGISTER_FAILED = 8,
+               BCE_ERROR_NO_PRIMARY = 9
+       } BCE_ERROR;
+
+#ifndef UNREFERENCED_PARAMETER
+#define    UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+       BCE_ERROR BC_Video_Register(int id);
+       BCE_ERROR BC_Video_Unregister(int id);
+       BCE_ERROR BC_Video_Buffers_Create(int id);
+       BCE_ERROR BC_Video_Buffers_Destroy(int id);
+       BCE_ERROR BC_Video_Init(int id);
+       BCE_ERROR BC_Video_Deinit(int id);
+
+       BCE_ERROR BCOpenPVRServices(BCE_HANDLE * phPVRServices);
+       BCE_ERROR BCClosePVRServices(BCE_HANDLE hPVRServices);
+
+       void *BCAllocKernelMem(unsigned long ulSize);
+       void BCFreeKernelMem(void *pvMem);
+
+       BCE_ERROR BCAllocDiscontigMemory(unsigned long ulSize,
+                                        BCE_HANDLE unref__ * phMemHandle,
+                                        IMG_CPU_VIRTADDR * pLinAddr,
+                                        IMG_SYS_PHYADDR ** ppPhysAddr);
+
+       void BCFreeDiscontigMemory(unsigned long ulSize,
+                                  BCE_HANDLE unref__ hMemHandle,
+                                  IMG_CPU_VIRTADDR LinAddr,
+                                  IMG_SYS_PHYADDR * pPhysAddr);
+
+       IMG_SYS_PHYADDR CpuPAddrToSysPAddrBC(IMG_CPU_PHYADDR cpu_paddr);
+       IMG_CPU_PHYADDR SysPAddrToCpuPAddrBC(IMG_SYS_PHYADDR sys_paddr);
+
+       void *MapPhysAddr(IMG_SYS_PHYADDR sSysAddr, unsigned long ulSize);
+       void UnMapPhysAddr(void *pvAddr, unsigned long ulSize);
+
+       BCE_ERROR BCGetLibFuncAddr(BCE_HANDLE hExtDrv, char *szFunctionName,
+                                  PFN_BC_GET_PVRJTABLE * ppfnFuncTable);
+       BC_VIDEO_DEVINFO *GetAnchorPtr(int id);
+       int GetBufferCount(unsigned int *puiBufferCount, int id);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/drivers/staging/mrst/bc_video/bufferclass_video_linux.c b/drivers/staging/mrst/bc_video/bufferclass_video_linux.c
new file mode 100644 (file)
index 0000000..cb51cea
--- /dev/null
@@ -0,0 +1,817 @@
+/****************************************************************************
+ *
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#if defined(LMA)
+#include <linux/pci.h>
+#else
+#include <linux/dma-mapping.h>
+#endif
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drv.h"
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_object.h"
+
+#include "bufferclass_video.h"
+#include "bufferclass_video_linux.h"
+#include "pvrmodule.h"
+#include "sys_pvr_drm_export.h"
+
+#define DEVNAME    "bc_video"
+#define    DRVNAME    DEVNAME
+
+#if defined(BCE_USE_SET_MEMORY)
+#undef BCE_USE_SET_MEMORY
+#endif
+
+#if defined(__i386__) && defined(SUPPORT_LINUX_X86_PAT) && defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+#include <asm/cacheflush.h>
+#define    BCE_USE_SET_MEMORY
+#endif
+
+unsigned int bc_video_id_usage[BC_VIDEO_DEVICE_MAX_ID];
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+int FillBuffer(unsigned int uiBufferIndex);
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+static struct class *psPvrClass;
+#endif
+
+static int AssignedMajorNumber;
+
+#define unref__ __attribute__ ((unused))
+
+#if defined(LMA)
+#define PVR_BUFFERCLASS_MEMOFFSET (220 * 1024 * 1024)
+#define PVR_BUFFERCLASS_MEMSIZE      (4 * 1024 * 1024)
+
+unsigned long g_ulMemBase = 0;
+unsigned long g_ulMemCurrent = 0;
+
+#define VENDOR_ID_PVR               0x1010
+#define DEVICE_ID_PVR               0x1CF1
+
+#define PVR_MEM_PCI_BASENUM         2
+#endif
+
+#define file_to_id(file)  (iminor(file->f_path.dentry->d_inode))
+
+int
+BC_Video_ModInit(void)
+{
+       int i, j;
+       /*LDM_PCI is defined, while LDM_PLATFORM and LMA are not defined.*/
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+       struct device *psDev;
+#endif
+
+#if defined(LMA)
+       struct pci_dev *psPCIDev;
+       int error;
+#endif
+
+#if defined(LMA)
+       psPCIDev = pci_get_device(VENDOR_ID_PVR, DEVICE_ID_PVR, NULL);
+       if (psPCIDev == NULL) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Video_ModInit:  pci_get_device failed\n");
+               goto ExitError;
+       }
+
+       if ((error = pci_enable_device(psPCIDev)) != 0) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Video_ModInit: pci_enable_device failed (%d)\n", error);
+               goto ExitError;
+       }
+#endif
+
+#if defined(DEBUG)
+       printk(KERN_ERR DRVNAME ": BC_Video_ModInit: major device %d\n",
+              AssignedMajorNumber);
+#endif
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+       psPvrClass = class_create(THIS_MODULE, "bc_video");
+       if (IS_ERR(psPvrClass)) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Video_ModInit: unable to create class (%ld)",
+                      PTR_ERR(psPvrClass));
+               goto ExitUnregister;
+       }
+
+       psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
+                       NULL, DEVNAME);
+       if (IS_ERR(psDev)) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Video_ModInit: unable to create device (%ld)",
+                      PTR_ERR(psDev));
+               goto ExitDestroyClass;
+       }
+#endif
+
+#if defined(LMA)
+       g_ulMemBase =
+               pci_resource_start(psPCIDev,
+                                  PVR_MEM_PCI_BASENUM) + PVR_BUFFERCLASS_MEMOFFSET;
+#endif
+
+       for (i = 0; i < BC_VIDEO_DEVICE_MAX_ID; i++) {
+               bc_video_id_usage[i] = 0;
+               if (BC_Video_Init(i) != BCE_OK) {
+                       printk(KERN_ERR DRVNAME
+                              ": BC_Video_ModInit: can't init video bc device %d.\n", i);
+                       for (j = i; j >= 0; j--) {
+                               BC_Video_Deinit(j);
+                       }
+                       goto ExitUnregister;
+               }
+       }
+
+       if (BC_Video_Init(BC_CAMERA_DEVICEID) != BCE_OK) {
+               for (i = BC_VIDEO_DEVICE_MAX_ID - 1; i >= 0; i--) {
+                       BC_Video_Deinit(i);
+               }
+               BC_Video_Deinit(BC_CAMERA_DEVICEID);
+               printk(KERN_ERR DRVNAME ": BC_Camera_ModInit: can't init device\n");
+               goto ExitUnregister;
+       }
+
+#if defined(LMA)
+       pci_disable_device(psPCIDev);
+#endif
+
+       return 0;
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ExitDestroyClass:
+       class_destroy(psPvrClass);
+#endif
+ExitUnregister:
+       unregister_chrdev(AssignedMajorNumber, DEVNAME);
+       //ExitDisable:
+#if defined(LMA)
+       pci_disable_device(psPCIDev);
+ExitError:
+#endif
+       return -EBUSY;
+}
+
+int
+BC_Video_ModCleanup(void)
+{
+       int i;
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+       device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+       class_destroy(psPvrClass);
+#endif
+
+       for (i = 0; i < BC_VIDEO_DEVICE_MAX_ID; i++) {
+               if (BC_Video_Deinit(i) != BCE_OK) {
+                       printk(KERN_ERR DRVNAME
+                              ": BC_Video_ModCleanup: can't deinit video device %d.\n",
+                              i);
+                       return -1;
+               }
+       }
+
+       if (BC_Video_Deinit(BC_CAMERA_DEVICEID) != BCE_OK) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Camera_ModCleanup: can't deinit device\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+void *
+BCAllocKernelMem(unsigned long ulSize)
+{
+       return kmalloc(ulSize, GFP_KERNEL);
+}
+
+void
+BCFreeKernelMem(void *pvMem)
+{
+       kfree(pvMem);
+}
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+#define    VMALLOC_TO_PAGE_PHYS(vAddr) page_to_phys(vmalloc_to_page(vAddr))
+
+BCE_ERROR
+BCAllocDiscontigMemory(unsigned long ulSize,
+                      BCE_HANDLE unref__ * phMemHandle,
+                      IMG_CPU_VIRTADDR * pLinAddr,
+                      IMG_SYS_PHYADDR ** ppPhysAddr)
+{
+       unsigned long ulPages = RANGE_TO_PAGES(ulSize);
+       IMG_SYS_PHYADDR *pPhysAddr;
+       unsigned long ulPage;
+       IMG_CPU_VIRTADDR LinAddr;
+
+       LinAddr =
+               __vmalloc(ulSize, GFP_KERNEL | __GFP_HIGHMEM,
+                         pgprot_noncached(PAGE_KERNEL));
+       if (!LinAddr) {
+               return BCE_ERROR_OUT_OF_MEMORY;
+       }
+
+       pPhysAddr = kmalloc(ulPages * sizeof(IMG_SYS_PHYADDR), GFP_KERNEL);
+       if (!pPhysAddr) {
+               vfree(LinAddr);
+               return BCE_ERROR_OUT_OF_MEMORY;
+       }
+
+       *pLinAddr = LinAddr;
+
+       for (ulPage = 0; ulPage < ulPages; ulPage++) {
+               pPhysAddr[ulPage].uiAddr = VMALLOC_TO_PAGE_PHYS(LinAddr);
+
+               LinAddr += PAGE_SIZE;
+       }
+
+       *ppPhysAddr = pPhysAddr;
+
+       return BCE_OK;
+}
+
+void
+BCFreeDiscontigMemory(unsigned long ulSize,
+                     BCE_HANDLE unref__ hMemHandle,
+                     IMG_CPU_VIRTADDR LinAddr, IMG_SYS_PHYADDR * pPhysAddr)
+{
+       kfree(pPhysAddr);
+
+       vfree(LinAddr);
+}
+
+static BCE_ERROR
+BCAllocContigMemory(unsigned long ulSize,
+                   BCE_HANDLE unref__ * phMemHandle,
+                   IMG_CPU_VIRTADDR * pLinAddr, IMG_CPU_PHYADDR * pPhysAddr)
+{
+#if defined(LMA)
+       void *pvLinAddr;
+
+
+       if (g_ulMemCurrent + ulSize >= PVR_BUFFERCLASS_MEMSIZE) {
+               return (BCE_ERROR_OUT_OF_MEMORY);
+       }
+
+       pvLinAddr = ioremap(g_ulMemBase + g_ulMemCurrent, ulSize);
+
+       if (pvLinAddr) {
+               pPhysAddr->uiAddr = g_ulMemBase + g_ulMemCurrent;
+               *pLinAddr = pvLinAddr;
+
+               g_ulMemCurrent += ulSize;
+               return (BCE_OK);
+       }
+       return (BCE_ERROR_OUT_OF_MEMORY);
+#else
+#if defined(BCE_USE_SET_MEMORY)
+       void *pvLinAddr;
+       unsigned long ulAlignedSize = PAGE_ALIGN(ulSize);
+       int iPages = (int)(ulAlignedSize >> PAGE_SHIFT);
+       int iError;
+
+       pvLinAddr = kmalloc(ulAlignedSize, GFP_KERNEL);
+       BUG_ON(((unsigned long) pvLinAddr) & ~PAGE_MASK);
+
+       iError = set_memory_wc((unsigned long) pvLinAddr, iPages);
+       if (iError != 0) {
+               printk(KERN_ERR DRVNAME
+                      ": BCAllocContigMemory:  set_memory_wc failed (%d)\n", iError);
+               return (BCE_ERROR_OUT_OF_MEMORY);
+       }
+
+       pPhysAddr->uiAddr = virt_to_phys(pvLinAddr);
+       *pLinAddr = pvLinAddr;
+
+       return (BCE_OK);
+#else
+       dma_addr_t dma;
+       void *pvLinAddr;
+
+       pvLinAddr = dma_alloc_coherent(NULL, ulSize, &dma, GFP_KERNEL);
+       if (pvLinAddr == NULL) {
+               return (BCE_ERROR_OUT_OF_MEMORY);
+       }
+
+       pPhysAddr->uiAddr = dma;
+       *pLinAddr = pvLinAddr;
+
+       return (BCE_OK);
+#endif
+#endif
+}
+
+static void
+BCFreeContigMemory(unsigned long ulSize,
+                  BCE_HANDLE unref__ hMemHandle,
+                  IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr)
+{
+#if defined(LMA)
+       g_ulMemCurrent -= ulSize;
+       iounmap(LinAddr);
+#else
+#if defined(BCE_USE_SET_MEMORY)
+       unsigned long ulAlignedSize = PAGE_ALIGN(ulSize);
+       int iError;
+       int iPages = (int)(ulAlignedSize >> PAGE_SHIFT);
+
+       iError = set_memory_wb((unsigned long) LinAddr, iPages);
+       if (iError != 0) {
+               printk(KERN_ERR DRVNAME
+                      ": BCFreeContigMemory:  set_memory_wb failed (%d)\n", iError);
+       }
+       kfree(LinAddr);
+#else
+       dma_free_coherent(NULL, ulSize, LinAddr, (dma_addr_t) PhysAddr.uiAddr);
+#endif
+#endif
+}
+
+IMG_SYS_PHYADDR
+CpuPAddrToSysPAddrBC(IMG_CPU_PHYADDR cpu_paddr)
+{
+       IMG_SYS_PHYADDR sys_paddr;
+       sys_paddr.uiAddr = cpu_paddr.uiAddr;
+       return sys_paddr;
+}
+
+IMG_CPU_PHYADDR
+SysPAddrToCpuPAddrBC(IMG_SYS_PHYADDR sys_paddr)
+{
+       IMG_CPU_PHYADDR cpu_paddr;
+       cpu_paddr.uiAddr = sys_paddr.uiAddr;
+       return cpu_paddr;
+}
+
+BCE_ERROR
+BCOpenPVRServices(BCE_HANDLE * phPVRServices)
+{
+       *phPVRServices = 0;
+       return (BCE_OK);
+}
+
+
+BCE_ERROR
+BCClosePVRServices(BCE_HANDLE unref__ hPVRServices)
+{
+       return (BCE_OK);
+}
+
+BCE_ERROR
+BCGetLibFuncAddr(BCE_HANDLE unref__ hExtDrv, char *szFunctionName,
+                PFN_BC_GET_PVRJTABLE * ppfnFuncTable)
+{
+       if (strcmp("PVRGetBufferClassJTable", szFunctionName) != 0) {
+               return (BCE_ERROR_INVALID_PARAMS);
+       }
+
+       *ppfnFuncTable = PVRGetBufferClassJTable;
+
+       return (BCE_OK);
+}
+
+static int
+BC_CreateBuffers(int id, bc_buf_params_t * p, IMG_BOOL is_conti_addr)
+{
+       BC_VIDEO_DEVINFO *psDevInfo;
+       IMG_UINT32 i, stride, size;
+       PVRSRV_PIXEL_FORMAT pixel_fmt;
+
+       if (p->count <= 0)
+               return -EINVAL;
+
+       if (p->width <= 1 || p->height <= 1)
+               return -EINVAL;
+
+       switch (p->fourcc) {
+       case BC_PIX_FMT_NV12:
+               pixel_fmt = PVRSRV_PIXEL_FORMAT_NV12;
+               break;
+       case BC_PIX_FMT_UYVY:
+               pixel_fmt = PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY;
+               break;
+       case BC_PIX_FMT_RGB565:
+               pixel_fmt = PVRSRV_PIXEL_FORMAT_RGB565;
+               p->stride = p->stride << 1;    /* stride for RGB from user space is uncorrect */
+               break;
+       case BC_PIX_FMT_YUYV:
+               pixel_fmt = PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+
+       stride = p->stride;
+
+       if (p->type != BC_MEMORY_MMAP && p->type != BC_MEMORY_USERPTR)
+               return -EINVAL;
+
+       if ((psDevInfo = GetAnchorPtr(id)) == IMG_NULL)
+               return -ENODEV;
+
+       if (psDevInfo->ulNumBuffers)
+               BC_DestroyBuffers(id);
+
+       psDevInfo->buf_type = p->type;
+       psDevInfo->psSystemBuffer =
+               BCAllocKernelMem(sizeof(BC_VIDEO_BUFFER) * p->count);
+
+       if (!psDevInfo->psSystemBuffer)
+               return -ENOMEM;
+
+       memset(psDevInfo->psSystemBuffer, 0, sizeof(BC_VIDEO_BUFFER) * p->count);
+       size = p->height * stride;
+       if (pixel_fmt == PVRSRV_PIXEL_FORMAT_NV12)
+               size += (stride >> 1) * (p->height >> 1) << 1;
+
+       for (i = 0; i < p->count; i++) {
+               IMG_SYS_PHYADDR *pPhysAddr;
+               psDevInfo->ulNumBuffers++;
+               psDevInfo->psSystemBuffer[i].ulSize = size;
+               psDevInfo->psSystemBuffer[i].psSyncData = IMG_NULL;
+
+               /*for discontig buffers, allocate memory for pPhysAddr */
+               psDevInfo->psSystemBuffer[i].is_conti_addr = is_conti_addr;
+               if (is_conti_addr) {
+                       pPhysAddr = BCAllocKernelMem(1 * sizeof(IMG_SYS_PHYADDR));
+                       if (!pPhysAddr) {
+                               return BCE_ERROR_OUT_OF_MEMORY;
+                       }
+                       memset(pPhysAddr, 0, 1 * sizeof(IMG_SYS_PHYADDR));
+               } else {
+                       unsigned long ulPages = RANGE_TO_PAGES(size);
+                       pPhysAddr = BCAllocKernelMem(ulPages * sizeof(IMG_SYS_PHYADDR));
+                       if (!pPhysAddr) {
+                               return BCE_ERROR_OUT_OF_MEMORY;
+                       }
+                       memset(pPhysAddr, 0, ulPages * sizeof(IMG_SYS_PHYADDR));
+               }
+               psDevInfo->psSystemBuffer[i].psSysAddr = pPhysAddr;
+       }
+       p->count = psDevInfo->ulNumBuffers;
+
+       psDevInfo->sBufferInfo.ui32BufferCount = psDevInfo->ulNumBuffers;
+       psDevInfo->sBufferInfo.pixelformat = pixel_fmt;
+       psDevInfo->sBufferInfo.ui32Width = p->width;
+       psDevInfo->sBufferInfo.ui32Height = p->height;
+       psDevInfo->sBufferInfo.ui32ByteStride = stride;
+       psDevInfo->sBufferInfo.ui32BufferDeviceID = id;
+       psDevInfo->sBufferInfo.ui32Flags = PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE |
+                                          PVRSRV_BC_FLAGS_YUVCSC_BT601;
+       return 0;
+}
+
+int
+BC_DestroyBuffers(int id)
+{
+       BC_VIDEO_DEVINFO *psDevInfo;
+       IMG_UINT32 i;
+       if ((psDevInfo = GetAnchorPtr(id)) == IMG_NULL)
+               return -ENODEV;
+
+       if (!psDevInfo->ulNumBuffers)
+               return 0;
+
+       for (i = 0; i < psDevInfo->ulNumBuffers; i++)
+               BCFreeKernelMem(psDevInfo->psSystemBuffer[i].psSysAddr);
+
+       BCFreeKernelMem(psDevInfo->psSystemBuffer);
+
+       psDevInfo->ulNumBuffers = 0;
+       psDevInfo->sBufferInfo.pixelformat = PVRSRV_PIXEL_FORMAT_UNKNOWN;
+       psDevInfo->sBufferInfo.ui32Width = 0;
+       psDevInfo->sBufferInfo.ui32Height = 0;
+       psDevInfo->sBufferInfo.ui32ByteStride = 0;
+       psDevInfo->sBufferInfo.ui32BufferDeviceID = id;
+       psDevInfo->sBufferInfo.ui32Flags = 0;
+       psDevInfo->sBufferInfo.ui32BufferCount = psDevInfo->ulNumBuffers;
+
+       return 0;
+}
+
+int
+GetBufferCount(unsigned int *puiBufferCount, int id)
+{
+       BC_VIDEO_DEVINFO *psDevInfo = GetAnchorPtr(id);
+
+       if (psDevInfo == IMG_NULL) {
+               return -1;
+       }
+
+       *puiBufferCount = (unsigned int) psDevInfo->sBufferInfo.ui32BufferCount;
+
+       return 0;
+}
+
+int
+BC_Video_Bridge(struct drm_device *dev, IMG_VOID * arg,
+               struct drm_file *file_priv)
+{
+       int err = -EFAULT;
+
+       BC_VIDEO_DEVINFO *devinfo;
+       int i;
+       BC_Video_ioctl_package *psBridge = (BC_Video_ioctl_package *) arg;
+       int command = psBridge->ioctl_cmd;
+       int id = 0;
+
+       if (command == BC_Video_ioctl_request_buffers) {
+               for (i = 0; i < BC_VIDEO_DEVICE_MAX_ID; i++) {
+                       if (bc_video_id_usage[i] == 0) {
+                               bc_video_id_usage[i] = 1;
+                               id = i;
+                               break;
+                       }
+               }
+               if (i == BC_VIDEO_DEVICE_MAX_ID) {
+                       printk(KERN_ERR DRVNAME
+                              " : Does you really need to run more than 5 video simulateously.\n");
+                       return -1;
+               } else
+                       psb_fpriv(file_priv)->bcd_index = id;
+       } else
+               id = psBridge->device_id;
+
+       if ((devinfo = GetAnchorPtr(id)) == IMG_NULL)
+               return -ENODEV;
+
+       switch (command) {
+       case BC_Video_ioctl_get_buffer_count: {
+               if (GetBufferCount(&psBridge->outputparam, id) == -1) {
+                       printk(KERN_ERR DRVNAME
+                              " : GetBufferCount error in BC_Video_Bridge.\n");
+                       return err;
+               }
+               return 0;
+               break;
+       }
+       case BC_Video_ioctl_get_buffer_index: {
+               int idx;
+               BC_VIDEO_BUFFER *buffer;
+
+               for (idx = 0; idx < devinfo->ulNumBuffers; idx++) {
+                       buffer = &devinfo->psSystemBuffer[idx];
+
+                       if (psBridge->inputparam == buffer->sBufferHandle) {
+                               psBridge->outputparam = idx;
+                               return 0;
+                       }
+               }
+               printk(KERN_ERR DRVNAME ": BCIOGET_BUFFERIDX- buffer not found\n");
+               return -EINVAL;
+               break;
+       }
+       case BC_Video_ioctl_request_buffers: {
+               bc_buf_params_t p;
+               if (copy_from_user
+                   (&p, (void __user *)(psBridge->inputparam), sizeof(p))) {
+                       printk(KERN_ERR " : failed to copy inputparam to kernel.\n");
+                       return -EFAULT;
+               }
+               psBridge->outputparam = id;
+               return BC_CreateBuffers(id, &p, IMG_FALSE);
+               break;
+       }
+       case BC_Video_ioctl_set_buffer_phyaddr: {
+               bc_buf_ptr_t p;
+               struct ttm_buffer_object *bo = NULL;
+               struct ttm_tt *ttm = NULL;
+               struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+
+               if (copy_from_user
+                   (&p, (void __user *)(psBridge->inputparam), sizeof(p))) {
+                       printk(KERN_ERR DRVNAME
+                              " : failed to copy inputparam to kernel.\n");
+                       return -EFAULT;
+               }
+
+               if (p.index >= devinfo->ulNumBuffers || !p.handle) {
+                       printk(KERN_ERR DRVNAME
+                              " : index big than NumBuffers or p.handle is NULL.\n");
+                       return -EINVAL;
+               }
+
+               bo = ttm_buffer_object_lookup(tfile, p.handle);
+               if (unlikely(bo == NULL)) {
+                       printk(KERN_ERR DRVNAME
+                              " : Could not find buffer object for setstatus.\n");
+                       return -EINVAL;
+               }
+               ttm = bo->ttm;
+
+               devinfo->psSystemBuffer[p.index].sCPUVAddr = NULL;
+               devinfo->psSystemBuffer[p.index].sBufferHandle = p.handle;
+               for (i = 0; i < ttm->num_pages; i++) {
+                       if (ttm->pages[i] == NULL) {
+                               printk(KERN_ERR " : Debug: the page is NULL.\n");
+                               return -EINVAL;
+                       }
+                       devinfo->psSystemBuffer[p.index].psSysAddr[i].uiAddr =
+                               page_to_pfn(ttm->pages[i]) << PAGE_SHIFT;
+               }
+               if (bo)
+                       ttm_bo_unref(&bo);
+               return 0;
+               break;
+       }
+       case BC_Video_ioctl_release_buffer_device: {
+               bc_video_id_usage[id] = 0;
+
+               BC_DestroyBuffers(id);
+               return 0;
+               break;
+       }
+       case BC_Video_ioctl_alloc_buffer: {
+               bc_buf_ptr_t p;
+               IMG_VOID *pvBuf;
+               IMG_UINT32 ui32Size;
+               IMG_UINT32 ulPagesNumber;
+               IMG_UINT32 ulCounter;
+               BUFFER_INFO *bufferInfo;
+
+               if (copy_from_user
+                   (&p, (void __user *)(psBridge->inputparam), sizeof(p))) {
+                       printk(KERN_ERR DRVNAME
+                              " : failed to copy inputparam to kernel.\n");
+                       return -EFAULT;
+               }
+
+               if (p.index >= devinfo->ulNumBuffers) {
+                       printk(KERN_ERR DRVNAME " : index big than NumBuffers.\n");
+                       return -EINVAL;
+               }
+
+               bufferInfo = &(devinfo->sBufferInfo);
+               if (bufferInfo->pixelformat != PVRSRV_PIXEL_FORMAT_NV12) {
+                       printk(KERN_ERR DRVNAME
+                              " : BC_Video_ioctl_alloc_buffer only support NV12 format.\n");
+                       return -EINVAL;
+               }
+               ui32Size = bufferInfo->ui32Height * bufferInfo->ui32ByteStride;
+               ui32Size +=
+                       (bufferInfo->ui32ByteStride >> 1) *
+                       (bufferInfo->ui32Height >> 1) << 1;
+
+               pvBuf =
+                       __vmalloc(ui32Size, GFP_KERNEL | __GFP_HIGHMEM,
+                                 __pgprot((pgprot_val(PAGE_KERNEL) & ~_PAGE_CACHE_MASK)
+                                          | _PAGE_CACHE_WC));
+               if (pvBuf == NULL) {
+                       printk(KERN_ERR DRVNAME
+                              " : Failed to allocate %d bytes buffer.\n", ui32Size);
+                       return -EINVAL;
+               }
+               devinfo->psSystemBuffer[p.index].sCPUVAddr = pvBuf;
+               devinfo->psSystemBuffer[p.index].sBufferHandle = 0;
+
+               ulPagesNumber = (ui32Size + PAGE_SIZE - 1) / PAGE_SIZE;
+               i = 0;
+
+               for (ulCounter = 0; ulCounter < ui32Size; ulCounter += PAGE_SIZE) {
+                       devinfo->psSystemBuffer[p.index].psSysAddr[i++].uiAddr =
+                               vmalloc_to_pfn(pvBuf + ulCounter) << PAGE_SHIFT;
+               }
+
+               if (p.handle) {
+                       printk(KERN_ERR DRVNAME
+                              " : fill data %d bytes from user space 0x%x.\n", ui32Size,
+                              (int) p.handle);
+                       if (copy_from_user(pvBuf, (void __user *) p.handle, ui32Size)) {
+                               printk(KERN_ERR DRVNAME
+                                      " : failed to copy inputparam to kernel.\n");
+                               return -EFAULT;
+                       }
+
+               }
+               psBridge->outputparam = (int) pvBuf;
+
+               return 0;
+               break;
+       }
+       case BC_Video_ioctl_free_buffer: {
+               bc_buf_ptr_t p;
+
+               if (copy_from_user
+                   (&p, (void __user *)(psBridge->inputparam), sizeof(p))) {
+                       printk(KERN_ERR DRVNAME
+                              " : failed to copy inputparam to kernel.\n");
+                       return -EFAULT;
+               }
+
+               vfree(devinfo->psSystemBuffer[p.index].sCPUVAddr);
+               return 0;
+               break;
+       }
+       default:
+               return err;
+       }
+
+       return 0;
+}
+
+static int
+BC_Camera_Bridge(BC_Video_ioctl_package * psBridge, unsigned long pAddr)
+{
+       int err = -EFAULT;
+
+       BC_VIDEO_DEVINFO *devinfo;
+       int id = BC_CAMERA_DEVICEID;
+       int command = psBridge->ioctl_cmd;
+
+       if ((devinfo = GetAnchorPtr(BC_CAMERA_DEVICEID)) == IMG_NULL)
+               return -ENODEV;
+
+       switch (command) {
+       case BC_Video_ioctl_get_buffer_count: {
+               if (GetBufferCount(&psBridge->outputparam, id) == -1) {
+                       printk(KERN_ERR DRVNAME
+                              " : GetBufferCount error in BC_Video_Bridge.\n");
+                       return err;
+               }
+               return 0;
+               break;
+       }
+       case BC_Video_ioctl_get_buffer_index: {
+               int idx;
+               BC_VIDEO_BUFFER *buffer;
+
+               for (idx = 0; idx < devinfo->ulNumBuffers; idx++) {
+                       buffer = &devinfo->psSystemBuffer[idx];
+
+                       if (psBridge->inputparam == buffer->sBufferHandle) {
+                               psBridge->outputparam = idx;
+                               return 0;
+                       }
+               }
+               printk(KERN_ERR DRVNAME ": BCIOGET_BUFFERIDX- buffer not found\n");
+               return -EINVAL;
+               break;
+       }
+       case BC_Video_ioctl_request_buffers: {
+               bc_buf_params_t p;
+               memcpy(&p, (void *)(psBridge->inputparam), sizeof(p));
+               return BC_CreateBuffers(id, &p, IMG_TRUE);
+               break;
+       }
+       case BC_Video_ioctl_set_buffer_phyaddr: {
+               bc_buf_ptr_t p;
+
+               memcpy(&p, (void *)(psBridge->inputparam), sizeof(p));
+               if (p.index >= devinfo->ulNumBuffers) {
+                       printk(KERN_ERR DRVNAME " : index big than NumBuffers\n");
+                       return -EINVAL;
+               }
+
+               /* Get the physical address of each frame */
+               devinfo->psSystemBuffer[p.index].psSysAddr[0].uiAddr =
+                       pAddr +
+                       p.index * PAGE_ALIGN(devinfo->psSystemBuffer[p.index].ulSize);
+
+               return 0;
+               break;
+       }
+       default:
+               return err;
+       }
+
+       return 0;
+}
diff --git a/drivers/staging/mrst/bc_video/bufferclass_video_linux.h b/drivers/staging/mrst/bc_video/bufferclass_video_linux.h
new file mode 100644 (file)
index 0000000..ca1109f
--- /dev/null
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ *
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ******************************************************************************/
+
+#ifndef __BC_VIDEO_LINUX_H__
+#define __BC_VIDEO_LINUX_H__
+
+#include <linux/ioctl.h>
+#include "bufferclass_video.h"
+
+#define BC_FOURCC(a,b,c,d) \
+    ((unsigned long) ((a) | (b)<<8 | (c)<<16 | (d)<<24))
+
+#define BC_PIX_FMT_NV12     BC_FOURCC('N', 'V', '1', '2')    /*YUV 4:2:0 */
+#define BC_PIX_FMT_UYVY     BC_FOURCC('U', 'Y', 'V', 'Y')    /*YUV 4:2:2 */
+#define BC_PIX_FMT_YUYV     BC_FOURCC('Y', 'U', 'Y', 'V')    /*YUV 4:2:2 */
+#define BC_PIX_FMT_RGB565   BC_FOURCC('R', 'G', 'B', 'P')    /*RGB 5:6:5 */
+
+typedef struct BC_Video_ioctl_package_TAG {
+       int ioctl_cmd;
+       int device_id;
+       int inputparam;
+       int outputparam;
+} BC_Video_ioctl_package;
+
+typedef struct bc_buf_ptr {
+       unsigned int index;
+       int size;
+       unsigned long pa;
+       unsigned long handle;
+} bc_buf_ptr_t;
+
+#define BC_Video_ioctl_fill_buffer              0
+#define BC_Video_ioctl_get_buffer_count         1
+#define BC_Video_ioctl_get_buffer_phyaddr       2    /*get physical address by index */
+#define BC_Video_ioctl_get_buffer_index         3    /*get index by physical address */
+#define BC_Video_ioctl_request_buffers          4
+#define BC_Video_ioctl_set_buffer_phyaddr       5
+#define BC_Video_ioctl_release_buffer_device    6
+
+#define BC_Video_ioctl_alloc_buffer             7
+#define BC_Video_ioctl_free_buffer              8
+
+int BC_DestroyBuffers(int id);
+
+extern unsigned int bc_video_id_usage[BC_VIDEO_DEVICE_MAX_ID];
+
+#endif
diff --git a/drivers/staging/mrst/drv/displays/hdmi.h b/drivers/staging/mrst/drv/displays/hdmi.h
new file mode 100644 (file)
index 0000000..984a04c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+#ifndef HDMI_H
+#define HDMI_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "mdfld_output.h"
+
+void hdmi_init(struct drm_device* dev);
+
+#endif
diff --git a/drivers/staging/mrst/drv/displays/tmd_vid.h b/drivers/staging/mrst/drv/displays/tmd_vid.h
new file mode 100644 (file)
index 0000000..42cf949
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+#ifndef TMD_VID_H
+#define TMD_VID_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "mdfld_output.h"
+
+void tmd_vid_init(struct drm_device* dev, struct panel_funcs* p_funcs);
+
+#endif
diff --git a/drivers/staging/mrst/drv/displays/tpo_cmd.h b/drivers/staging/mrst/drv/displays/tpo_cmd.h
new file mode 100644 (file)
index 0000000..bb018c2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+
+#ifndef TPO_CMD_H
+#define TPO_CMD_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "mdfld_output.h"
+
+void tpo_cmd_init(struct drm_device* dev, struct panel_funcs* p_funcs);
+
+#endif
diff --git a/drivers/staging/mrst/drv/displays/tpo_vid.h b/drivers/staging/mrst/drv/displays/tpo_vid.h
new file mode 100644 (file)
index 0000000..63c86bb
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+#ifndef TPO_VID_H
+#define TPO_VID_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "mdfld_output.h"
+
+void tpo_vid_init(struct drm_device* dev, struct panel_funcs* p_funcs);
+
+#endif
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dbi.c b/drivers/staging/mrst/drv/mdfld_dsi_dbi.c
new file mode 100644 (file)
index 0000000..cc38331
--- /dev/null
@@ -0,0 +1,725 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *  jim liu <jim.liu@intel.com>
+ *  Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "psb_powermgmt.h"
+
+static int enter_dsr;
+struct mdfld_dsi_dbi_output *gdbi_output;
+
+#define MDFLD_DSR_MAX_IDLE_COUNT       2
+#define MDFLD_DSI_MAX_RETURN_PACKET_SIZE       512
+
+/**
+ * set refreshing area
+ */
+int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output * dbi_output,
+                               u16 x1, u16 y1, u16 x2, u16 y2)
+{
+       struct mdfld_dsi_pkg_sender * sender = 
+               mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+       u8 param[5];
+       int err;
+
+       if(!sender) {
+               DRM_ERROR("Cannot get PKG sender\n");
+               return -EINVAL;
+       }
+
+       /*set column*/
+       param[0] = DCS_SET_COLUMN_ADDRESS;
+       param[1] = x1 >> 8;
+       param[2] = x1;
+       param[3] = x2 >> 8;
+       param[4] = x2;
+
+       err = mdfld_dsi_send_mcs_long(sender, param, 5, true);
+       if(err) {
+               DRM_ERROR("DCS_SET_COLUMN_ADDRESS sent failed\n");
+               goto err_out;
+       }
+
+       /*set page*/
+       param[0] = DCS_SET_PAGE_ADDRESS;
+       param[1] = y1 >> 8;
+       param[2] = y1;
+       param[3] = y2 >> 8;
+       param[4] = y2;
+
+       err = mdfld_dsi_send_mcs_long(sender, param, 5, true);
+       if(err) {
+               DRM_ERROR("DCS_SET_PAGE_ADDRESS sent failed\n");
+               goto err_out;
+       }
+
+       /*update screen*/
+       err = mdfld_dsi_write_mem_start(sender);
+       if(err) {
+               DRM_ERROR("DCS_WRITE_MEM_START sent failed\n");
+               goto err_out;
+        }
+
+err_out:
+        return err;
+}
+
+/**
+ * set panel's power state
+ */ 
+int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output * dbi_output, int mode)
+{
+       struct drm_device * dev = dbi_output->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dsi_pkg_sender * sender = 
+               mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+       u32 err = 0;
+       
+       if(!sender) {
+               DRM_ERROR("Cannot get PKG sender\n");
+               return -EINVAL;
+       }
+       
+       if(mode == DRM_MODE_DPMS_ON) {
+               /*exit sleep mode*/
+               err = mdfld_dsi_send_mcs_short(sender, DCS_EXIT_SLEEP_MODE,
+                                       0, 0, true);
+               if (err) {
+                       DRM_ERROR("DCS 0x%x sent failed\n",
+                                       DCS_EXIT_SLEEP_MODE);
+                       goto power_err;
+               }
+
+               /*set display on*/
+               err = mdfld_dsi_send_mcs_short(sender, DCS_SET_DISPLAY_ON,
+                                       0, 0, true);
+               if (err) {
+                       DRM_ERROR("DCS 0x%x sent failed\n",
+                                       DCS_SET_DISPLAY_ON);
+                       goto power_err;
+               }
+               
+               /* set tear effect on */
+               err = mdfld_dsi_send_mcs_short(sender, DCS_SET_TEAR_ON,
+                                       0, 1, true);
+               if (err) {
+                       DRM_ERROR("DCS 0x%x sent failed\n", DCS_SET_TEAR_ON);
+                       goto power_err;
+               }
+               
+               /**
+                * FIXME: remove this later
+                */ 
+               err = mdfld_dsi_write_mem_start(sender);
+               if (err) {
+                       DRM_ERROR("DCS 0x%x sent failed\n",
+                                       DCS_WRITE_MEM_START);
+                       goto power_err;
+               }
+       } else {
+               /*set tear effect off */
+               err = mdfld_dsi_send_mcs_short(sender, DCS_SET_TEAR_OFF,
+                                       0, 0, true);
+               if (err) {
+                       DRM_ERROR("DCS 0x%x sent failed\n", set_tear_off);
+                       goto power_err;
+               }
+               
+               /*set display off*/
+               err = mdfld_dsi_send_mcs_short(sender, DCS_SET_DISPLAY_OFF,
+                                       0, 0, true);
+               if (err) {
+                       DRM_ERROR("DCS 0x%x sent failed\n",
+                                       DCS_SET_DISPLAY_OFF);
+                       goto power_err;
+               }               
+               
+               /*enter sleep mode*/
+               err = mdfld_dsi_send_mcs_short(sender, DCS_ENTER_SLEEP_MODE,
+                                       0, 0, true);
+               if (err) {
+                       DRM_ERROR("DCS 0x%x sent failed\n",
+                                       DCS_ENTER_SLEEP_MODE);
+                       goto power_err;
+               }
+       }
+       
+power_err:
+       return err;
+}
+
+/**
+ * Enter DSR 
+ */
+void mdfld_dsi_dbi_enter_dsr (struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+       u32 reg_val;
+       struct drm_device * dev = dbi_output->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct drm_crtc * crtc = dbi_output->base.base.crtc;
+       struct psb_intel_crtc * psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; 
+       u32 dpll_reg = MRST_DPLL_A;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dspcntr_reg = DSPACNTR;
+       u32 dspbase_reg = DSPABASE;
+       u32 dspsurf_reg = DSPASURF;
+
+       PSB_DEBUG_ENTRY(" \n");
+       
+       if(!dbi_output)
+               return;
+       
+       gdbi_output = dbi_output;
+       if((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) 
+               return;
+               
+       if(pipe == 2) {
+               dpll_reg = MRST_DPLL_A;
+               pipeconf_reg = PIPECCONF;
+               dspcntr_reg = DSPCCNTR;
+               dspbase_reg = MDFLD_DSPCBASE;
+               dspsurf_reg = DSPCSURF;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+               DRM_ERROR("hw begin failed\n");
+               return;
+       }
+               
+       /*disable te interrupts. */
+       mdfld_disable_te(dev, pipe);
+
+       /*disable plane*/
+       reg_val = REG_READ(dspcntr_reg);
+       if(!(reg_val & DISPLAY_PLANE_ENABLE)) {
+               REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE);
+               REG_READ(dspcntr_reg);
+       }
+       
+       /*disable pipe*/
+       reg_val = REG_READ(pipeconf_reg);
+       if(!(reg_val & DISPLAY_PLANE_ENABLE)) {
+               reg_val &= ~DISPLAY_PLANE_ENABLE;
+               reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF);
+               REG_WRITE(pipeconf_reg, reg_val);
+               REG_READ(pipeconf_reg);
+               mdfldWaitForPipeDisable(dev, pipe);
+       }
+       
+       /*disable DPLL*/
+       reg_val = REG_READ(dpll_reg);
+       if(!(reg_val & DPLL_VCO_ENABLE)) {
+               reg_val &= ~DPLL_VCO_ENABLE;
+               REG_WRITE(dpll_reg, reg_val);
+               REG_READ(dpll_reg);
+               udelay(500);
+       }
+       
+       /*gate power of DSI DPLL*/
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       
+       /*update mode state to IN_DSR*/
+       dbi_output->mode_flags |= MODE_SETTING_IN_DSR;
+
+       if(pipe == 2){
+               enter_dsr = 1;
+#ifdef CONFIG_PM_RUNTIME
+               pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay);
+#endif
+       }
+}
+
+#ifndef CONFIG_MDFLD_DSI_DPU
+static void mdfld_dbi_output_exit_dsr (struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+       struct drm_device * dev = dbi_output->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct drm_crtc * crtc = dbi_output->base.base.crtc;
+       struct psb_intel_crtc * psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; 
+       u32 reg_val;
+       u32 dpll_reg = MRST_DPLL_A;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dspcntr_reg = DSPACNTR;
+
+       /*if mode setting on-going, back off*/
+       if((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) 
+               return;
+               
+       if(pipe == 2) {
+               dpll_reg = MRST_DPLL_A;
+               pipeconf_reg = PIPECCONF;
+               dspcntr_reg = DSPCCNTR;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+               DRM_ERROR("hw begin failed\n");
+               return;
+       }
+
+       /*enable DPLL*/
+       reg_val = REG_READ(dpll_reg);
+       if(!(reg_val & DPLL_VCO_ENABLE)) {
+               
+               if(reg_val & MDFLD_PWR_GATE_EN) {
+                       reg_val &= ~MDFLD_PWR_GATE_EN;
+                       REG_WRITE(dpll_reg, reg_val);
+                       REG_READ(dpll_reg);
+                       udelay(500);
+               }
+               
+               reg_val |= DPLL_VCO_ENABLE;
+               REG_WRITE(dpll_reg, reg_val);
+               REG_READ(dpll_reg);
+               udelay(500);
+               
+               /*add timeout*/
+               while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+                       cpu_relax();
+               }
+       }
+       
+       /*enable pipe*/
+       reg_val = REG_READ(pipeconf_reg);
+       if(!(reg_val & PIPEACONF_ENABLE)) {
+               reg_val |= PIPEACONF_ENABLE;
+               REG_WRITE(pipeconf_reg, reg_val);
+               REG_READ(pipeconf_reg);
+               udelay(500);
+               mdfldWaitForPipeEnable(dev, pipe);
+       }
+       
+       /*enable plane*/
+       reg_val = REG_READ(dspcntr_reg);
+       if(!(reg_val & DISPLAY_PLANE_ENABLE)) {
+               reg_val |= DISPLAY_PLANE_ENABLE;
+               REG_WRITE(dspcntr_reg, reg_val);
+               REG_READ(dspcntr_reg);
+               udelay(500);
+       }
+
+       /*enable TE interrupt on this pipe*/
+       mdfld_enable_te(dev, pipe);
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       /*clean IN_DSR flag*/
+       dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+}
+
+/**
+ * Exit from DSR 
+ */
+void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct mdfld_dbi_dsr_info * dsr_info = dev_priv->dbi_dsr_info;
+       struct mdfld_dsi_dbi_output ** dbi_output;
+       int i;
+       int pipe;
+       
+       PSB_DEBUG_ENTRY("\n");
+
+       dbi_output = dsr_info->dbi_outputs;
+
+#ifdef CONFIG_PM_RUNTIME
+        if(drm_psb_ospm && !enable_gfx_rtpm) {
+//                pm_runtime_allow(&gpDrmDevice->pdev->dev);
+               schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000);
+        }
+#endif
+
+       /*for each output, exit dsr*/
+       for(i=0; i<dsr_info->dbi_output_num; i++) {
+               /*if panel has been turned off, skip*/
+               if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on)
+                       continue;
+
+               pipe = dbi_output[i]->channel_num ? 2 : 0;
+               enter_dsr = 0;
+               mdfld_dbi_output_exit_dsr(dbi_output[i], pipe);
+       }
+       
+       dev_priv->dsr_fb_update |= update_src;
+}
+
+static bool mdfld_dbi_is_in_dsr(struct drm_device * dev)
+{
+       if(REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE)
+               return false;
+       if((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) ||
+          (REG_READ(PIPECCONF) & PIPEACONF_ENABLE))
+               return false;
+       if((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) ||
+          (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE))
+               return false;
+       
+       return true;
+}
+
+/* Perodically update dbi panel */
+void mdfld_dbi_update_panel (struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+       struct mdfld_dsi_dbi_output **dbi_outputs;
+       struct mdfld_dsi_dbi_output *dbi_output;
+       int i;
+       int can_enter_dsr = 0;
+       int enter_dsr = 0;
+       u32 damage_mask = 0;
+
+       dbi_outputs = dsr_info->dbi_outputs;
+       dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
+
+       if (!dbi_output)
+               return;
+
+       if (pipe == 0)
+               damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0;
+       else if (pipe == 2)
+               damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2;
+       else
+               return;
+
+       /*if FB is damaged and panel is on update on-panel FB*/
+       if (damage_mask && dbi_output->dbi_panel_on) {
+               dbi_output->dsr_fb_update_done = false;
+
+               if (dbi_output->p_funcs->update_fb)
+                       dbi_output->p_funcs->update_fb(dbi_output, pipe);
+
+               if (dev_priv->b_dsr_enable && dbi_output->dsr_fb_update_done)
+                       dev_priv->dsr_fb_update &= ~damage_mask;
+
+               /*clean IN_DSR flag*/
+               dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+               dbi_output->dsr_idle_count = 0;
+
+       } else {
+               dbi_output->dsr_idle_count++;
+       }
+
+       switch (dsr_info->dbi_output_num) {
+       case 1:
+               if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
+                       can_enter_dsr = 1;
+               break;
+       case 2:
+               if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT
+                  && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
+                       can_enter_dsr = 1;
+               break;
+       default:
+               DRM_ERROR("Wrong DBI output number\n");
+               can_enter_dsr = 0;
+       }
+
+       /*try to enter DSR*/
+       if (can_enter_dsr) {
+               for(i=0; i<dsr_info->dbi_output_num; i++) {
+                       if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] &&
+                          !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
+                               mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
+                                       dbi_outputs[i]->channel_num ? 2 : 0);
+#if 0
+                               enter_dsr = 1;
+                               printk(KERN_ALERT "%s: enter_dsr = 1 \n", __func__);
+#endif
+                       }
+               }
+       /*schedule rpm suspend after gfxrtdelay*/
+#ifdef CONFIG_PM_RUNTIME
+               if(!dev_priv->rpm_enabled
+                       || !enter_dsr
+       //              || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN)
+                       || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay))
+                       PSB_DEBUG_ENTRY("Runtime PM schedule suspend failed, rpm %d\n", dev_priv->rpm_enabled);
+#endif         
+       }
+}
+
+int mdfld_dbi_dsr_init(struct drm_device * dev) 
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dsr_info * dsr_info = dev_priv->dbi_dsr_info;
+       
+       if(!dsr_info || IS_ERR(dsr_info)) {
+               dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info), GFP_KERNEL);
+               if(!dsr_info) {
+                       DRM_ERROR("No memory\n");
+                       return -ENOMEM;
+               }
+               
+               dev_priv->dbi_dsr_info = dsr_info;
+       }
+
+       PSB_DEBUG_ENTRY("successfully\n");
+       
+       return 0;
+}
+
+void mdfld_dbi_dsr_exit(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dsr_info * dsr_info = dev_priv->dbi_dsr_info;
+       
+       if(!dsr_info) {
+               return;
+       }
+       
+       /*free dsr info*/
+       kfree(dsr_info);
+       
+       dev_priv->dbi_dsr_info = NULL;
+}
+#endif
+
+void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+       struct drm_device * dev = dsi_config->dev;
+       int lane_count = dsi_config->lane_count;
+       u32 val = 0;
+
+       PSB_DEBUG_ENTRY("Init DBI interface on pipe %d...\n", pipe);
+
+       /*un-ready device*/
+       REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0x00000000);
+       
+       /*init dsi adapter before kicking off*/
+       REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
+       
+       /*TODO: figure out how to setup these registers*/
+       REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408);
+       REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), 0x000a0014);
+       REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000400);
+       REG_WRITE(MIPI_DBI_FIFO_THROTTLE_REG(pipe), 0x00000001);
+       REG_WRITE(MIPI_HS_LS_DBI_ENABLE_REG(pipe), 0x00000000);
+       
+       /*enable all interrupts*/
+       REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
+       /*max value: 20 clock cycles of txclkesc*/
+       REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x0000001f);
+       /*min 21 txclkesc, max: ffffh*/
+       REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0x0000ffff);
+       /*min: 7d0 max: 4e20*/
+       REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x00000fa0);
+               
+       /* set up max return packet size */
+       REG_WRITE(MIPI_MAX_RETURN_PACK_SIZE_REG(pipe),
+               MDFLD_DSI_MAX_RETURN_PACKET_SIZE);
+
+       /*set up func_prg*/
+       val |= lane_count;
+       val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
+       val |= DSI_DBI_COLOR_FORMAT_OPTION2;
+       REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val);
+       
+       REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0x3fffff);
+       REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffff);
+
+       /*de-assert dbi_stall when half of DBI FIFO is empty*/
+       //REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000);
+       
+       REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46);
+       REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
+       REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
+       REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0x00000001);
+}
+
+#if 0
+/*DBI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
+       .dpms = mdfld_dsi_dbi_dpms,
+       .mode_fixup = mdfld_dsi_dbi_mode_fixup,
+       .prepare = mdfld_dsi_dbi_prepare,
+       .mode_set = mdfld_dsi_dbi_mode_set,
+       .commit = mdfld_dsi_dbi_commit,
+};
+
+/*DBI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+#endif
+
+/*
+ * Init DSI DBI encoder. 
+ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
+ * return pointer of newly allocated DBI encoder, NULL on error
+ */ 
+struct mdfld_dsi_encoder * mdfld_dsi_dbi_init(struct drm_device * dev, 
+                                       struct mdfld_dsi_connector * dsi_connector,
+                                       struct panel_funcs* p_funcs)
+{
+       struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+       struct mdfld_dsi_dbi_output * dbi_output = NULL;
+       struct mdfld_dsi_config * dsi_config;
+       struct drm_connector * connector = NULL;
+       struct drm_encoder * encoder = NULL;
+       struct drm_display_mode * fixed_mode = NULL;
+       struct psb_gtt * pg = dev_priv ? (dev_priv->pg) : NULL;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
+#else
+       struct mdfld_dbi_dsr_info * dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
+#endif 
+       u32 data = 0;
+       int pipe;
+       int ret;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if (!pg || !dsi_connector || !p_funcs) {
+               DRM_ERROR("Invalid parameters\n");
+               return NULL;
+       }
+
+       dsi_config = mdfld_dsi_get_config(dsi_connector);
+       pipe = dsi_connector->pipe;
+
+       /*panel hard-reset*/
+       if (p_funcs->reset) {
+               ret = p_funcs->reset(pipe);
+               if (ret) {
+                       DRM_ERROR("Panel %d hard-reset failed\n", pipe);
+                       return NULL;
+               }
+       }
+
+       /*panel drvIC init*/
+       if (p_funcs->drv_ic_init)
+               p_funcs->drv_ic_init(dsi_config, pipe);
+
+       /*panel power mode detect*/
+       ret = mdfld_dsi_get_power_mode(dsi_config, &data, true);
+       if (ret) {
+               DRM_ERROR("Panel %d get power mode failed\n", pipe);
+
+               dsi_connector->status = connector_status_disconnected;
+       } else {
+               DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
+
+               dsi_connector->status = connector_status_connected;
+       }
+
+       /*TODO: get panel info from DDB*/
+
+       dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
+       if(!dbi_output) {
+               DRM_ERROR("No memory\n");
+               return NULL;
+       }
+
+       if(dsi_connector->pipe == 0) {
+               dbi_output->channel_num = 0;
+               dev_priv->dbi_output = dbi_output;
+       } else if (dsi_connector->pipe == 2) {
+               dbi_output->channel_num = 1;
+               dev_priv->dbi_output2 = dbi_output;
+       } else {
+               DRM_ERROR("only support 2 DSI outputs\n");
+               goto out_err1;
+       }
+       
+       dbi_output->dev = dev;
+       dbi_output->p_funcs = p_funcs;
+       
+       /*get fixed mode*/
+       fixed_mode = dsi_config->fixed_mode;
+       
+       dbi_output->panel_fixed_mode = fixed_mode;
+       
+       /*create drm encoder object*/
+       connector = &dsi_connector->base.base;
+       encoder = &dbi_output->base.base;
+       drm_encoder_init(dev,
+                       encoder,
+                       p_funcs->encoder_funcs,
+                       DRM_MODE_ENCODER_LVDS);
+       drm_encoder_helper_add( encoder,
+                               p_funcs->encoder_helper_funcs);
+       
+       /*attach to given connector*/
+       drm_mode_connector_attach_encoder(connector, encoder);
+       
+       /*set possible crtcs and clones*/
+       if(dsi_connector->pipe) {
+               encoder->possible_crtcs = (1 << 2);
+               encoder->possible_clones = (1 << 1);
+       } else {
+               encoder->possible_crtcs = (1 << 0);
+               encoder->possible_clones = (1 << 0);
+       }
+
+       dev_priv->dsr_fb_update = 0;
+       dev_priv->b_dsr_enable = false;
+       
+       dbi_output->first_boot = true;
+       dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+       /*add this output to dpu_info*/
+
+       if (dsi_connector->status == connector_status_connected) {
+               if (dsi_connector->pipe == 0)
+                       dpu_info->dbi_outputs[0] = dbi_output;
+               else
+                       dpu_info->dbi_outputs[1] = dbi_output;
+
+               dpu_info->dbi_output_num++;
+       }
+
+#else /*CONFIG_MDFLD_DSI_DPU*/ 
+       if (dsi_connector->status == connector_status_connected) {
+               /*add this output to dsr_info*/
+               if (dsi_connector->pipe == 0)
+                       dsr_info->dbi_outputs[0] = dbi_output;
+               else
+                       dsr_info->dbi_outputs[1] = dbi_output;
+
+               dsr_info->dbi_output_num++;
+       }
+#endif
+
+       PSB_DEBUG_ENTRY("successfully\n");
+       
+       return &dbi_output->base;
+       
+out_err1: 
+       if(dbi_output) {
+               kfree(dbi_output);
+       }
+       
+       return NULL;
+}
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dbi.h b/drivers/staging/mrst/drv/mdfld_dsi_dbi.h
new file mode 100644 (file)
index 0000000..04d3fba
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DBI_H__
+#define __MDFLD_DSI_DBI_H__
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+/*
+ * DBI encoder which inherits from mdfld_dsi_encoder 
+ */ 
+struct mdfld_dsi_dbi_output {
+        struct mdfld_dsi_encoder base;
+
+        struct drm_display_mode * panel_fixed_mode;
+
+        u8 last_cmd;
+
+        u8 lane_count;
+
+        u8 channel_num;
+        
+        struct drm_device * dev;
+
+        /*backlight operations*/
+
+        u32 dsr_idle_count;
+        bool dsr_fb_update_done;
+        
+        /*mode setting flags*/
+        u32 mode_flags;
+        
+        /*panel status*/
+        bool dbi_panel_on;
+        bool first_boot;
+       struct panel_funcs* p_funcs;
+};
+
+#define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base)
+
+struct mdfld_dbi_dsr_info {
+       int dbi_output_num;
+       struct mdfld_dsi_dbi_output * dbi_outputs[2];
+       
+       u32 dsr_idle_count;
+};
+
+#define DBI_CB_TIMEOUT_COUNT   0xffff
+
+/*offsets*/
+#define CMD_MEM_ADDR_OFFSET    0
+
+#define CMD_DATA_SRC_SYSTEM_MEM        0
+#define CMD_DATA_SRC_PIPE      1
+
+static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output * dbi_output)
+{
+       struct drm_device * dev = dbi_output->dev;
+       u32 retry = DBI_CB_TIMEOUT_COUNT;
+       int pipe = dbi_output->channel_num == 1 ? 2 : 0;
+       int ret = 0;
+
+        /*query the dbi fifo status*/
+        retry = DBI_CB_TIMEOUT_COUNT;
+        while(retry--) {
+                if (REG_READ(MIPI_GEN_FIFO_STAT_REG(pipe)) & BIT(27))
+                        break;
+        }
+
+        if(!retry) {
+                DRM_ERROR("Timeout waiting for DBI FIFO empty\n");
+                ret = -EAGAIN;
+        }
+
+       return ret;     
+}
+
+static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output * dbi_output)
+{
+       struct drm_device * dev = dbi_output->dev;
+       u32 retry = DBI_CB_TIMEOUT_COUNT;
+       int pipe = dbi_output->channel_num == 1 ? 2 : 0;
+       int ret = 0;
+
+        /*query the command execution status*/
+        while(retry--) {
+                if (!(REG_READ(MIPI_CMD_ADD_REG(pipe)) & BIT(0)))
+                        break;
+        }
+
+        if(!retry) {
+                DRM_ERROR("Timeout waiting for DBI Command status\n");
+                ret = -EAGAIN;
+        }
+
+       return ret;
+}
+
+static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output * dbi_output)
+{
+       int ret = 0;
+
+       /*query the command execution status*/
+       ret = mdfld_dsi_dbi_cmd_sent(dbi_output);
+       if(ret) {
+               DRM_ERROR("Perpheral is busy\n");
+               ret = -EAGAIN;
+       }
+       /*query the dbi fifo status*/
+       ret = mdfld_dsi_dbi_fifo_ready(dbi_output);
+       if(ret) {
+               DRM_ERROR("DBI FIFO is not empty\n");
+               ret = -EAGAIN;
+       }
+
+       return ret;
+}
+
+/*export functions*/
+extern void mdfld_dsi_dbi_output_init(struct drm_device * dev, struct psb_intel_mode_device * mode_dev, int pipe);
+extern void mdfld_dsi_dbi_exit_dsr (struct drm_device *dev, u32 update_src);
+extern void mdfld_dsi_dbi_enter_dsr (struct mdfld_dsi_dbi_output * dbi_output, int pipe);
+extern int mdfld_dbi_dsr_init(struct drm_device * dev);
+extern void mdfld_dbi_dsr_exit(struct drm_device * dev);
+extern struct mdfld_dsi_encoder * mdfld_dsi_dbi_init(struct drm_device * dev, 
+                               struct mdfld_dsi_connector * dsi_connector,
+                               struct panel_funcs* p_funcs);
+extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output * dbi_output, u16 x1, u16 y1, u16 x2, u16 y2);
+extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output * dbi_output, int mode);
+extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe);
+
+extern struct mdfld_dsi_dbi_output *gdbi_output;
+
+#endif /*__MDFLD_DSI_DBI_H__*/
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.c b/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.c
new file mode 100644 (file)
index 0000000..6a096ad
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+ #include "mdfld_dsi_dbi_dpu.h"
+ #include "mdfld_dsi_dbi.h"
+/**
+ * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock
+ */
+static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info * dpu_info, 
+                                                          mdfld_plane_t plane,
+                                                          struct psb_drm_dpu_rect * damaged_rect)
+{
+       int x, y;
+       int new_x, new_y;
+       struct psb_drm_dpu_rect * rect;
+       struct psb_drm_dpu_rect * pipe_rect;
+       int cursor_size;
+       struct mdfld_cursor_info * cursor;
+       mdfld_plane_t fb_plane;
+       
+       if(plane == MDFLD_CURSORA) {
+               cursor = &dpu_info->cursors[0];
+               x = dpu_info->cursors[0].x;
+               y = dpu_info->cursors[0].y;
+               cursor_size = dpu_info->cursors[0].size;
+               pipe_rect = &dpu_info->damage_pipea;
+               fb_plane = MDFLD_PLANEA;
+       } else {
+               cursor = &dpu_info->cursors[1];
+               x = dpu_info->cursors[1].x;
+               y = dpu_info->cursors[1].y;
+               cursor_size = dpu_info->cursors[1].size;
+               pipe_rect = &dpu_info->damage_pipec;
+               fb_plane = MDFLD_PLANEC;
+       }
+       new_x = damaged_rect->x;
+       new_y = damaged_rect->y;
+       
+       if((x == new_x) && (y == new_y)) {
+               return 0;
+       }
+       
+       rect = &dpu_info->damaged_rects[plane];
+       
+       /*move to right*/
+       if(new_x >= x) {
+               if(new_y > y) {
+                       rect->x = x;
+                       rect->y = y;
+                       rect->width = (new_x + cursor_size) - x;
+                       rect->height = (new_y + cursor_size) - y;
+                       goto cursor_out;
+               } else {
+                       rect->x = x;
+                       rect->y = new_y;
+                       rect->width = (new_x + cursor_size) - x;
+                       rect->height = (y - new_y);
+                       goto cursor_out;
+               }
+       } else {
+               if(new_y > y) {
+                       rect->x = new_x;
+                       rect->y = y;
+                       rect->width = (x + cursor_size) - new_x;
+                       rect->height = new_y - y;
+                       goto cursor_out;
+               } else {
+                       rect->x = new_x;
+                       rect->y = new_y;
+                       rect->width = (x + cursor_size) - new_x;
+                       rect->height = (y + cursor_size) - new_y;
+               }
+       }
+cursor_out:
+       if(new_x < 0) {
+               cursor->x = 0;
+       } else if (new_x > 864) {
+               cursor->x = 864;
+       } else {
+               cursor->x = new_x;
+       }
+       
+       if(new_y < 0) {
+               cursor->y = 0;
+       } else if (new_y > 480) {
+               cursor->y = 480;
+       } else {
+               cursor->y = new_y;
+       }
+
+       /**
+        * FIXME: this is a workaround for cursor plane update, remove it later!
+        */
+       rect->x = 0;
+       rect->y = 0;
+       rect->width = 864;
+       rect->height = 480;
+       
+       mdfld_check_boundary(dpu_info, rect);
+       
+       mdfld_dpu_region_extent(pipe_rect, rect);
+       
+       /*update pending status of dpu_info*/
+       dpu_info->pending |= (1 << plane);
+       
+       /*update fb panel as well*/
+       dpu_info->pending |= (1 << fb_plane);
+       
+       return 0;
+}
+
+static int mdfld_fb_damage(struct mdfld_dbi_dpu_info * dpu_info,
+                                                  mdfld_plane_t plane,
+                                                  struct psb_drm_dpu_rect * damaged_rect)
+{
+       struct psb_drm_dpu_rect * rect;
+
+       if(plane == MDFLD_PLANEA) {
+               rect = &dpu_info->damage_pipea;
+       } else {
+               rect = &dpu_info->damage_pipec;
+       }
+       mdfld_check_boundary(dpu_info, damaged_rect);
+       
+       /*add fb damage area to this pipe*/
+       mdfld_dpu_region_extent(rect, damaged_rect);
+       
+       /*update pending status of dpu_info*/
+       dpu_info->pending |= (1 << plane);
+       return 0; 
+}
+
+/*do nothing here, right now*/
+static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info * dpu_info,
+                                                               mdfld_plane_t plane,
+                                                               struct psb_drm_dpu_rect * damaged_rect)
+{
+       PSB_DEBUG_ENTRY("\n");
+       
+       return 0;
+}
+
+int mdfld_dbi_dpu_report_damage(struct drm_device * dev,
+                               mdfld_plane_t plane,
+                               struct psb_drm_dpu_rect * rect)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+       int ret = 0;
+       
+       /*request lock*/
+       spin_lock(&dpu_info->dpu_update_lock);
+
+       switch(plane) {
+               case MDFLD_PLANEA:
+               case MDFLD_PLANEC:
+                       mdfld_fb_damage(dpu_info, plane, rect);
+                       break;
+               case MDFLD_CURSORA:
+               case MDFLD_CURSORC:
+                       mdfld_cursor_damage(dpu_info, plane, rect);
+                       break;
+               case MDFLD_OVERLAYA:
+               case MDFLD_OVERLAYC:
+                       mdfld_overlay_damage(dpu_info, plane, rect);
+                       break;
+               default:
+                       DRM_ERROR("Invalid plane type %d\n", plane);
+                       ret = -EINVAL;
+       }
+
+       spin_unlock(&dpu_info->dpu_update_lock);
+       return ret;
+}
+
+int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv;
+       struct mdfld_dbi_dpu_info * dpu_info;
+       struct mdfld_dsi_config  * dsi_config;
+       struct psb_drm_dpu_rect rect;
+       int i;
+
+       if(!dev) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       dev_priv = dev->dev_private;
+       dpu_info = dev_priv ? dev_priv->dbi_dpu_info : NULL;
+
+       if(!dpu_info) {
+               DRM_ERROR("No dpu info found\n");
+               return -EINVAL;
+       }
+
+       for(i=0; i<dpu_info->dbi_output_num; i++) {
+               dsi_config = dev_priv->dsi_configs[i];
+               if(dsi_config) {
+                       rect.x = rect.y = 0;
+                       rect.width = dsi_config->fixed_mode->hdisplay;
+                       rect.height = dsi_config->fixed_mode->vdisplay;
+                       mdfld_dbi_dpu_report_damage(dev,
+                                                   i ? (MDFLD_PLANEC) : (MDFLD_PLANEA),
+                                                   &rect);
+
+               }
+       }
+
+       /*exit DSR state*/
+       mdfld_dpu_exit_dsr(dev);
+
+       return 0;
+}                                                              
+
+
+int mdfld_dsi_dbi_dsr_off(struct drm_device * dev, struct psb_drm_dpu_rect * rect)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+       
+       mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect);
+       
+       /*if dual display mode*/
+       if(dpu_info->dbi_output_num == 2)
+               mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect);
+       
+       /*force dsi to exit DSR mode*/
+       mdfld_dpu_exit_dsr(dev);
+       
+       return 0;
+}
+
+static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info * dpu_info,
+                                                                                mdfld_plane_t plane) 
+{
+       struct drm_device * dev = dpu_info->dev;
+       u32 curpos_reg = CURAPOS;
+       u32 curbase_reg = CURABASE;
+       u32 curcntr_reg = CURACNTR;
+       struct mdfld_cursor_info * cursor = &dpu_info->cursors[0];
+       
+       if(plane == MDFLD_CURSORC) {
+               curpos_reg = CURCPOS;
+               curbase_reg = CURCBASE;
+               curcntr_reg = CURCCNTR;
+               cursor = &dpu_info->cursors[1];
+       }
+       
+       REG_WRITE(curcntr_reg, REG_READ(curcntr_reg));  
+       REG_WRITE(curpos_reg, (((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | ((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT)));
+       REG_WRITE(curbase_reg, REG_READ(curbase_reg));
+}
+
+static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info * dpu_info,
+                                                                        mdfld_plane_t plane)
+{
+       u32 pipesrc_reg = PIPEASRC;
+       u32 dspsize_reg = DSPASIZE;
+       u32 dspoff_reg = DSPALINOFF;
+       u32 dspsurf_reg = DSPASURF;
+       u32 dspstride_reg = DSPASTRIDE;
+       u32 stride;
+       struct psb_drm_dpu_rect * rect = &dpu_info->damage_pipea;
+       struct drm_device * dev = dpu_info->dev;
+       
+       if(plane == MDFLD_PLANEC) {
+               pipesrc_reg = PIPECSRC;
+               dspsize_reg = DSPCSIZE;
+               dspoff_reg = DSPCLINOFF;
+               dspsurf_reg = DSPCSURF;
+               dspstride_reg = DSPCSTRIDE;
+               
+               rect = &dpu_info->damage_pipec;
+       }
+
+       stride = REG_READ(dspstride_reg);
+       /*FIXME: should I do the pipe src update here?*/
+       REG_WRITE(pipesrc_reg, ((rect->width -1) << 16) | (rect->height -1));
+       /*flush plane*/
+       REG_WRITE(dspsize_reg, ((rect->height-1) << 16) | (rect->width - 1));
+       REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride)));
+       REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+       
+       /**
+        * TODO: wait for flip finished and restore the pipesrc reg, 
+        * or cursor will be show at a wrong position
+        */
+}
+
+static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info * dpu_info,
+                                                                                 mdfld_plane_t plane)
+{
+       PSB_DEBUG_ENTRY("\n");
+}
+
+/**
+ * TODO: we are still in dbi normal mode now, will try to use partial mode later. 
+ */
+static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output * dbi_output, 
+                                                       struct mdfld_dbi_dpu_info * dpu_info, int pipe)
+{
+       u8 * cb_addr = (u8 *)dbi_output->dbi_cb_addr;
+       u32 * index;
+       struct psb_drm_dpu_rect * rect = pipe ? (&dpu_info->damage_pipec) : (&dpu_info->damage_pipea);
+       
+       /*FIXME: lock command buffer, this may lead to a dead lock, we've already hold the dpu_update_lock*/
+       if(!spin_trylock(&dbi_output->cb_lock)) {
+               DRM_ERROR("lock command buffer failed, try again\n");
+               return -EAGAIN;
+       }
+       
+       index = &dbi_output->cb_write;
+       
+       if(*index) {
+               DRM_ERROR("DBI command buffer unclean\n");
+               return -EAGAIN;
+       }
+       
+       /*column address*/
+       *(cb_addr + ((*index)++)) = set_column_address;
+       *(cb_addr + ((*index)++)) = rect->x >> 8;
+       *(cb_addr + ((*index)++)) = rect->x;
+       *(cb_addr + ((*index)++)) = (rect->x + rect->width -1) >> 8;
+       *(cb_addr + ((*index)++)) = (rect->x + rect->width -1);
+       
+       *index = 8;
+
+       /*page address*/
+       *(cb_addr + ((*index)++)) = set_page_addr;
+       *(cb_addr + ((*index)++)) = rect->y >> 8;
+       *(cb_addr + ((*index)++)) = rect->y;
+       *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8;
+       *(cb_addr + ((*index)++)) = (rect->y + rect->height -1 );
+
+       *index = 16;
+       
+       /*write memory*/
+       *(cb_addr + ((*index)++)) = write_mem_start;
+       
+       return 0;
+}
+
+static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+       u32 cmd_phy = dbi_output->dbi_cb_phy;
+       u32 * index = &dbi_output->cb_write;
+       struct drm_device * dev = dbi_output->dev;
+       
+       if(*index == 0 || !dbi_output) {
+               return 0;
+       }
+       
+       REG_WRITE(MIPI_CMD_LEN_REG(pipe), 0x010505);
+       REG_WRITE(MIPI_CMD_ADD_REG(pipe), cmd_phy | BIT(0) | BIT(1));
+       
+       *index = 0;
+       
+       /*FIXME: unlock command buffer*/
+       spin_unlock(&dbi_output->cb_lock);
+       
+       return 0;
+}
+
+static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output * dbi_output,
+                                                                struct mdfld_dbi_dpu_info * dpu_info, int pipe)
+{
+       struct drm_device * dev =  dbi_output->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       mdfld_plane_t cursor_plane = MDFLD_CURSORA; 
+       mdfld_plane_t fb_plane = MDFLD_PLANEA;
+       mdfld_plane_t overlay_plane = MDFLD_OVERLAYA;
+       int ret = 0;
+       u32 plane_mask = MDFLD_PIPEA_PLANE_MASK;
+       
+       /*damaged rects on this pipe*/
+       if(pipe) {
+               cursor_plane = MDFLD_CURSORC;
+               fb_plane = MDFLD_PLANEC;
+               overlay_plane = MDFLD_OVERLAYC;
+               plane_mask = MDFLD_PIPEC_PLANE_MASK;
+       }
+       
+       /*update cursor which assigned to @pipe*/
+       if(dpu_info->pending & (1 << cursor_plane)) 
+               mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane);
+       
+       /*update fb which assigned to @pipe*/
+       if(dpu_info->pending & (1 << fb_plane)) 
+               mdfld_dpu_fb_plane_flush(dpu_info, fb_plane);
+       
+       /*TODO: update overlay*/
+       if(dpu_info->pending & (1 << overlay_plane)) 
+               mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane);
+       
+       /*flush damage area to panel fb*/
+       if(dpu_info->pending & plane_mask) {
+               ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe);
+       
+               /**
+                * TODO: remove b_dsr_enable later, 
+                * added it so that text console could boot smoothly
+                */
+               /*clean pending flags on this pipe*/
+               if(!ret && dev_priv->b_dsr_enable) {
+                       dpu_info->pending &= ~plane_mask;
+               
+                       /*reset overlay pipe damage rect*/
+                       mdfld_dpu_init_damage(dpu_info, pipe);
+               }
+       }
+
+       return ret;
+}
+
+static int mdfld_dpu_update_fb(struct drm_device * dev) {
+       struct drm_crtc * crtc;
+       struct psb_intel_crtc * psb_crtc;
+       struct mdfld_dsi_dbi_output ** dbi_output;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+       bool pipe_updated[2];
+       unsigned long irq_flags;
+       u32 dpll_reg = MRST_DPLL_A;
+       u32 dspcntr_reg = DSPACNTR;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dsplinoff_reg = DSPALINOFF;
+       u32 dspsurf_reg = DSPASURF;
+       int pipe;
+       int i;
+       int ret;
+
+       dbi_output = dpu_info->dbi_outputs;
+       pipe_updated[0] = pipe_updated[1] = false;
+       
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+               return -EAGAIN;
+
+       /*try to prevent any new damage reports*/       
+       if(!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags)) {
+               return -EAGAIN;
+       }
+
+       for(i=0; i<dpu_info->dbi_output_num; i++) {
+               crtc = dbi_output[i]->base.base.crtc;
+               psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; 
+
+                pipe = dbi_output[i]->channel_num ? 2 : 0;
+
+                if(pipe == 2) {
+                        dspcntr_reg = DSPCCNTR;
+                        pipeconf_reg = PIPECCONF;
+                        dsplinoff_reg = DSPCLINOFF;
+                        dspsurf_reg = DSPCSURF;
+                }
+
+                if (!(REG_READ(MIPI_GEN_FIFO_STAT_REG(pipe)) & BIT(27)) ||
+                   !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+                   !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+                   !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
+                        PSB_DEBUG_ENTRY("DBI FIFO is busy, DSI %d state %x\n",
+                                        pipe,
+                                        REG_READ(MIPI_INTR_STAT_REG(pipe)));
+                        continue;
+                }
+
+               /*if dbi output is in a exclusive state, pipe change won't be updated*/
+               if(dbi_output[i]->dbi_panel_on &&
+                  !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) &&
+                  !(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) &&
+                  !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
+                       ret = mdfld_dpu_update_pipe(dbi_output[i], dpu_info, dbi_output[i]->channel_num ? 2 : 0);
+                       if(!ret) {
+                               pipe_updated[i] = true;
+                       }
+               } 
+       }
+       
+       for(i=0; i<dpu_info->dbi_output_num; i++) {
+               if(pipe_updated[i]) {
+                       mdfld_dbi_flush_cb(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0);
+               }
+       }
+
+       spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags);
+       
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       
+       return 0;
+}
+
+static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+       struct drm_device * dev = dbi_output->dev;
+       struct drm_crtc * crtc = dbi_output->base.base.crtc;
+       struct psb_intel_crtc * psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; 
+       u32 reg_val;
+       u32 dpll_reg = MRST_DPLL_A;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dspcntr_reg = DSPACNTR;
+       u32 dspbase_reg = DSPABASE;
+       u32 dspsurf_reg = DSPASURF;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if(!dbi_output) {
+               return 0;
+       }
+
+       /*if mode setting on-going, back off*/
+       if((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) 
+               return -EAGAIN;
+               
+       if(pipe == 2) {
+               dpll_reg = MRST_DPLL_A;
+               pipeconf_reg = PIPECCONF;
+               dspcntr_reg = DSPCCNTR;
+               dspbase_reg = MDFLD_DSPCBASE;
+               dspsurf_reg = DSPCSURF;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+               return -EAGAIN;
+
+       /*enable DPLL*/
+       reg_val = REG_READ(dpll_reg);
+       if(!(reg_val & DPLL_VCO_ENABLE)) {
+               
+               if(reg_val & MDFLD_PWR_GATE_EN) {
+                       reg_val &= ~MDFLD_PWR_GATE_EN;
+                       REG_WRITE(dpll_reg, reg_val);
+                       REG_READ(dpll_reg);
+                       udelay(500);
+               }
+               
+               reg_val |= DPLL_VCO_ENABLE;
+               REG_WRITE(dpll_reg, reg_val);
+               REG_READ(dpll_reg);
+               udelay(500);
+               
+               /*FIXME: add timeout*/
+               while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK));
+       }
+       
+       /*enable pipe*/
+       reg_val = REG_READ(pipeconf_reg);
+       if(!(reg_val & PIPEACONF_ENABLE)) {
+               reg_val |= PIPEACONF_ENABLE;
+               REG_WRITE(pipeconf_reg, reg_val);
+               REG_READ(pipeconf_reg);
+               udelay(500);
+               mdfldWaitForPipeEnable(dev, pipe);
+       }
+       
+       /*enable plane*/
+       reg_val = REG_READ(dspcntr_reg);
+       if(!(reg_val & DISPLAY_PLANE_ENABLE)) {
+               reg_val |= DISPLAY_PLANE_ENABLE;
+               REG_WRITE(dspcntr_reg, reg_val);
+               REG_READ(dspcntr_reg);
+               udelay(500);
+       }
+       
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       
+       /*clean IN_DSR flag*/
+       dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+       
+       return 0;
+}
+
+int mdfld_dpu_exit_dsr(struct drm_device * dev)
+{
+       struct mdfld_dsi_dbi_output ** dbi_output;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+       int i;
+       int pipe;
+       
+       dbi_output = dpu_info->dbi_outputs;
+       
+       for(i=0; i<dpu_info->dbi_output_num; i++) {
+               /*if this output is not in DSR mode, don't call exit dsr*/
+               if(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR) {
+                       __mdfld_dbi_exit_dsr(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0);
+               }
+       }
+
+       /*enable te interrupt*/
+       for (i = 0; i < dpu_info->dbi_output_num; i++) {
+               /*if this output is not in DSR mode, don't call exit dsr*/
+               pipe = dbi_output[i]->channel_num ? 2 : 0;
+               if (dbi_output[i]->dbi_panel_on && pipe) {
+                       mdfld_disable_te(dev, 0);
+                       mdfld_enable_te(dev, 2);
+               } else if (dbi_output[i]->dbi_panel_on && !pipe) {
+                       mdfld_disable_te(dev, 2);
+                       mdfld_enable_te(dev, 0);
+               }
+       }
+
+       return 0;
+       
+}
+
+static int mdfld_dpu_enter_dsr(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+       struct mdfld_dsi_dbi_output ** dbi_output;
+       int i;
+       
+       PSB_DEBUG_ENTRY("\n");
+       
+       dbi_output = dpu_info->dbi_outputs;
+       
+       for(i=0; i<dpu_info->dbi_output_num; i++) {
+               /*if output is off or already in DSR state, don't enter again*/
+               if(dbi_output[i]->dbi_panel_on && 
+                  !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
+                       mdfld_dsi_dbi_enter_dsr(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0);
+               }
+       }
+
+       return 0;
+}
+
+static void mdfld_dbi_dpu_timer_func(unsigned long data)
+{
+       struct drm_device * dev = (struct drm_device *)data;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+       struct timer_list * dpu_timer = &dpu_info->dpu_timer;
+       unsigned long flags;
+       
+       if(dpu_info->pending) {
+               dpu_info->idle_count = 0;
+               
+               /*update panel fb with damaged area*/
+               mdfld_dpu_update_fb(dev);
+       } else {
+               dpu_info->idle_count++;
+       }
+
+       if(dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+               /*enter dsr*/
+               mdfld_dpu_enter_dsr(dev);
+               
+               /*stop timer by return*/
+               return;
+       }
+
+       spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+       if(!timer_pending(dpu_timer)){
+               dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+               add_timer(dpu_timer);
+       }
+       spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+}
+
+void mdfld_dpu_update_panel(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+
+       if(dpu_info->pending) {
+               dpu_info->idle_count = 0;
+
+               /*update panel fb with damaged area*/
+               mdfld_dpu_update_fb(dev);
+       } else {
+               dpu_info->idle_count++;
+       }
+
+       if(dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+               /*enter dsr*/
+               mdfld_dpu_enter_dsr(dev);
+       }
+}
+
+static int mdfld_dbi_dpu_timer_init(struct drm_device * dev, struct mdfld_dbi_dpu_info * dpu_info)
+{
+       struct timer_list * dpu_timer = &dpu_info->dpu_timer;
+       unsigned long flags;
+               
+       PSB_DEBUG_ENTRY("\n");
+
+       spin_lock_init(&dpu_info->dpu_timer_lock);
+       spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+       
+       init_timer(dpu_timer);
+       
+       dpu_timer->data = (unsigned long)dev;
+       dpu_timer->function = mdfld_dbi_dpu_timer_func;
+       dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+       
+       spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+       
+       PSB_DEBUG_ENTRY("successfully\n");
+       
+       return 0;
+}
+
+int mdfld_dbi_dpu_init(struct drm_device * dev) 
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+       
+       if(!dpu_info || IS_ERR(dpu_info)) {
+               dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info), GFP_KERNEL);
+               if(!dpu_info) {
+                       DRM_ERROR("No memory\n");
+                       return -ENOMEM;
+               }
+               
+               dev_priv->dbi_dpu_info = dpu_info;
+       }
+       
+       dpu_info->dev = dev;
+       
+       dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE;
+       dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE;
+       
+       /*init dpu_update_lock*/
+       spin_lock_init(&dpu_info->dpu_update_lock);
+       
+       /*init dpu refresh timer*/
+       mdfld_dbi_dpu_timer_init(dev, dpu_info);
+       
+       /*init pipe damage area*/
+       mdfld_dpu_init_damage(dpu_info, 0);
+       mdfld_dpu_init_damage(dpu_info, 2);
+       
+       PSB_DEBUG_ENTRY("successfully\n");
+       
+       return 0;
+}
+
+void mdfld_dbi_dpu_exit(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+       
+       if(!dpu_info) {
+               return;
+       }
+       
+       /*delete dpu timer*/
+       del_timer_sync(&dpu_info->dpu_timer);
+       
+       /*free dpu info*/
+       kfree(dpu_info);
+       
+       dev_priv->dbi_dpu_info = NULL;
+}
+
+
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.h b/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.h
new file mode 100644 (file)
index 0000000..a74a5e1
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DBI_DPU_H__
+#define __MDFLD_DSI_DBI_DPU_H__
+
+#include "mdfld_dsi_dbi.h"
+
+typedef enum {
+       MDFLD_PLANEA,
+       MDFLD_PLANEC,
+       MDFLD_CURSORA,
+       MDFLD_CURSORC,
+       MDFLD_OVERLAYA,
+       MDFLD_OVERLAYC,
+       MDFLD_PLANE_NUM,
+} mdfld_plane_t;
+
+#define MDFLD_PIPEA_PLANE_MASK 0x15    
+#define MDFLD_PIPEC_PLANE_MASK 0x2A
+
+struct mdfld_cursor_info {
+       int x, y;
+       int size;
+};
+
+#define MDFLD_CURSOR_SIZE      64
+
+/**
+ * enter DSR mode if screen has no update for 2 frames.
+ * TODO: export this as a configuration variable. 
+ * (or what's the PRD for this?)
+ */
+#define MDFLD_MAX_IDLE_COUNT   2       
+
+struct mdfld_dbi_dpu_info {
+       struct drm_device * dev;
+       /*lock*/
+       spinlock_t dpu_update_lock;
+       
+       /*cursor postion*/
+       struct mdfld_cursor_info cursors[2];
+               
+       /*damaged area for each plane*/
+       struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM];
+       
+       /*final damaged area*/
+       struct psb_drm_dpu_rect damage_pipea;
+       struct psb_drm_dpu_rect damage_pipec;
+       
+       /*pending*/
+       u32 pending;
+       
+       /*dpu timer*/
+       struct timer_list dpu_timer;
+       spinlock_t dpu_timer_lock;
+       
+       /*dpu idle count*/
+       u32 idle_count;
+       
+       /*dsi outputs*/
+       struct mdfld_dsi_dbi_output * dbi_outputs[2];
+       int dbi_output_num;
+};
+
+static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect * origin,
+                                                        struct psb_drm_dpu_rect * rect)
+{
+       int x1, y1, x2, y2;
+
+       /*PSB_DEBUG_ENTRY("rect (%d, %d, %d, %d)\n", rect->x, rect->y, rect->width, rect->height);*/
+       
+       x1 = origin->x + origin->width;
+       y1 = origin->y + origin->height;
+       
+       x2 = rect->x + rect->width;
+       y2 = rect->y + rect->height;
+       
+       origin->x = min(origin->x, rect->x);
+       origin->y = min(origin->y, rect->y);
+       origin->width = max(x1, x2) - origin->x;
+       origin->height = max(y1, y2) - origin->y;
+       
+       return 0;
+}
+
+static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info * dpu_info, 
+                                                                               struct psb_drm_dpu_rect * rect)
+{
+       if(rect->x < 0)
+               rect->x = 0;
+       if(rect->y < 0)
+               rect->y = 0;
+       
+       if((rect->x + rect->width) > 864) {
+               rect->width = 864 - rect->x;
+       }
+       
+       if((rect->y + rect->height) > 480) {
+               rect->height = 480 - rect->height;
+       }
+       
+       if(!rect->width)
+               rect->width = 1;
+       if(!rect->height)
+               rect->height = 1;
+}
+
+static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info * dpu_info, int pipe) {
+       struct psb_drm_dpu_rect * rect;
+       
+       if(pipe == 0) {
+               rect = &dpu_info->damage_pipea;
+       } else {
+               rect = &dpu_info->damage_pipec;
+       }
+       
+       rect->x = 864;
+       rect->y = 480;
+       rect->width = -864;
+       rect->height = -480;
+}
+
+extern int mdfld_dsi_dbi_dsr_off(struct drm_device * dev, struct psb_drm_dpu_rect * rect);
+extern int mdfld_dbi_dpu_report_damage(struct drm_device * dev,
+                                       mdfld_plane_t plane,
+                                       struct psb_drm_dpu_rect * rect);
+extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device * dev);
+extern int mdfld_dpu_exit_dsr(struct drm_device * dev);
+extern int mdfld_dbi_dpu_init(struct drm_device * dev);
+extern void mdfld_dbi_dpu_exit(struct drm_device * dev);
+extern void mdfld_dpu_update_panel(struct drm_device * dev);
+
+#endif /*__MDFLD_DSI_DBI_DPU_H__*/
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dpi.c b/drivers/staging/mrst/drv/mdfld_dsi_dpi.c
new file mode 100644 (file)
index 0000000..b960908
--- /dev/null
@@ -0,0 +1,1115 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "psb_powermgmt.h"
+#include "psb_drv.h"
+#include "tc35876x-dsi-lvds.h"
+
+static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe);
+static bool dsi_device_ready = true; /* for TC35876X */
+
+static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
+{
+       u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+       int timeout = 0;
+
+       udelay(500);
+
+       /* This will time out after approximately 2+ seconds */
+       while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
+               udelay(100);
+               timeout++;
+       }
+
+       if (timeout == 20000)
+               DRM_INFO("MIPI: HS Data FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+       u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+       int timeout = 0;
+
+       udelay(500);
+
+       /* This will time out after approximately 2+ seconds */
+       while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) {
+               udelay(100);
+               timeout++;
+       }
+       if (timeout == 20000)
+               DRM_INFO("MIPI: HS CMD FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+       u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+        int timeout = 0;
+
+        udelay(500);
+
+        /* This will time out after approximately 2+ seconds */
+        while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY)
+                                                        != DPI_FIFO_EMPTY)) {
+                udelay(100);
+                timeout++;
+        }
+
+        if (timeout == 20000)
+                DRM_INFO("MIPI: DPI FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
+{
+       u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
+       int timeout = 0;
+
+        udelay(500);
+
+        /* This will time out after approximately 2+ seconds */
+        while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) {
+                udelay(100);
+                timeout++;
+        }
+
+        if (timeout == 20000)
+                DRM_INFO("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
+}
+
+/* For TC35876X */
+static void mdfld_wait_for_PIPEA_DISABLE(struct drm_device *dev, u32 pipe)
+{
+        u32 pipeconf_reg = PIPEACONF;
+        int timeout = 0;
+
+        if (pipe == 2)
+                pipeconf_reg = PIPECCONF;
+
+        udelay(500);
+
+        /* This will time out after approximately 2+ seconds */
+        while ((timeout < 20000) && (REG_READ(pipeconf_reg) & 0x40000000)) {
+                udelay(100);
+                timeout++;
+        }
+
+        if (timeout == 20000)
+                DRM_INFO("MIPI: PIPE was not disabled!\n");
+}
+
+static void dsi_set_device_ready_state(struct drm_device *dev, int state,
+                               int pipe)
+{
+       printk(KERN_ALERT "[DISPLAY TRK] %s: state = %d, pipe = %d\n", __func__, state, pipe);
+
+       REG_WRITE(MIPI_DEVICE_READY_REG(pipe), state ? BIT(0) : 0);
+}
+
+static void dsi_set_pipe_plane_enable_state(struct drm_device *dev, int state, int pipe)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dspcntr_reg = DSPACNTR;
+
+       u32 pipeconf = dev_priv->pipeconf;
+       u32 dspcntr = dev_priv->dspcntr;
+       u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+
+       printk(KERN_ALERT "[DISPLAY TRK] %s: state = %d, pipe = %d\n", __func__, state, pipe);
+
+       if (pipe) {
+               pipeconf_reg = PIPECCONF;
+               dspcntr_reg = DSPCCNTR;
+       } else {
+               mipi &= (~0x03);
+       }
+
+       if (state) {
+
+               /*Set up pipe */
+               REG_WRITE(pipeconf_reg, pipeconf);
+
+               /*Set up display plane */
+               REG_WRITE(dspcntr_reg, dspcntr);
+       } else {
+               /*Disable PIPE */
+               REG_WRITE(pipeconf_reg, 0);
+               mdfld_wait_for_PIPEA_DISABLE(dev, pipe);
+               mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
+
+       }
+}
+
+static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder * dsi_encoder, int pipe)
+{
+       struct mdfld_dsi_dpi_output * dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+       struct drm_device * dev = dsi_config->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+
+       printk(KERN_ALERT "[DISPLAY TRK] Enter %s\n", __func__);
+
+       if (!dev_priv->dpi_panel_on) {
+               printk(KERN_ALERT "[DISPLAY] %s: DPI Panel is Already Off\n", __func__);
+               return;
+       }
+       tc35876x_set_bridge_reset_state(1);
+       dsi_set_pipe_plane_enable_state(dev, 0, pipe);  //Disable pipe and plane
+
+       mdfld_dsi_dpi_shut_down(dpi_output, pipe);  //Send shut down command
+
+       dsi_set_device_ready_state(dev, 0, pipe);  //Clear device ready state
+
+       dev_priv->dpi_panel_on = false;
+}
+
+static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder * dsi_encoder, int pipe)
+{
+       struct mdfld_dsi_dpi_output * dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+       struct drm_device * dev = dsi_config->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+
+       printk(KERN_ALERT "[DISPLAY TRK] Enter %s\n", __func__);
+
+       if (dev_priv->dpi_panel_on) {
+               printk(KERN_ALERT "[DISPLAY] %s: DPI Panel is Already On\n", __func__);
+               return;
+       }
+
+       /* For resume path sequence */
+       mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+       dsi_set_device_ready_state(dev, 0, pipe);  //Clear Device Ready Bit
+
+       dsi_set_device_ready_state(dev, 1, pipe);  //Set device ready state
+       tc35876x_set_bridge_reset_state(0);
+       tc35876x_configure_lvds_bridge(dev);
+       mdfld_dsi_dpi_turn_on(dpi_output, pipe);  //Send turn on command
+       dsi_set_pipe_plane_enable_state(dev, 1, pipe);  //Enable plane and pipe
+
+       dev_priv->dpi_panel_on = true;
+}
+/* End for TC35876X */
+
+/* ************************************************************************* *\
+ * FUNCTION: mdfld_dsi_tpo_ic_init
+ *
+ * DESCRIPTION:  This function is called only by mrst_dsi_mode_set and
+ *               restore_display_registers.  since this function does not
+ *               acquire the mutex, it is important that the calling function
+ *               does!
+\* ************************************************************************* */
+static void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config * dsi_config, u32 pipe)
+{
+       struct drm_device * dev = dsi_config->dev;
+       u32 dcsChannelNumber = dsi_config->channel_num;
+       u32 gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
+       u32 gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
+       u32 gen_ctrl_val = GEN_LONG_WRITE;
+
+       DRM_INFO("Enter mrst init TPO MIPI display.\n");
+
+       gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
+
+       /* Flip page order */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x00008036);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
+
+       /* 0xF0 */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x005a5af0);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+       /* Write protection key */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x005a5af1);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+       /* 0xFC */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x005a5afc);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+       /* 0xB7 */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x770000b7);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x00000044);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
+
+       /* 0xB6 */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x000a0ab6);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+       /* 0xF2 */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x081010f2);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x4a070708);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x000000c5);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+       /* 0xF8 */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x024003f8);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x01030a04);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x0e020220);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x00000004);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
+
+       /* 0xE2 */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x398fc3e2);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x0000916f);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
+
+       /* 0xB0 */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x000000b0);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
+
+       /* 0xF4 */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x240242f4);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x78ee2002);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x2a071050);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x507fee10);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x10300710);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
+
+       /* 0xBA */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x19fe07ba);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x101c0a31);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x00000010);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+       /* 0xBB */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x28ff07bb);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x24280a31);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x00000034);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+       /* 0xFB */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x535d05fb);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x1b1a2130);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x221e180e);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x131d2120);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x535d0508);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x1c1a2131);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x231f160d);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x111b2220);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x535c2008);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x1f1d2433);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x2c251a10);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x2c34372d);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x00000023);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
+
+       /* 0xFA */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x525c0bfa);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x1c1c232f);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x2623190e);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x18212625);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x545d0d0e);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x1e1d2333);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x26231a10);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x1a222725);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x545d280f);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x21202635);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x31292013);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x31393d33);
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x00000029);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
+
+       /* Set DM */
+       mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+       REG_WRITE(gen_data_reg, 0x000100f7);
+       mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+       REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+}
+
+static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, int num_lane, int bpp)
+{
+       return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); 
+}
+
+/*
+ * Calculate the dpi time basing on a given drm mode @mode
+ * return 0 on success.
+ * FIXME: I was using proposed mode value for calculation, may need to 
+ * use crtc mode values later 
+ */
+int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode * mode, 
+                                                                       struct mdfld_dsi_dpi_timing * dpi_timing,
+                                                                       int num_lane, int bpp)
+{
+       int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
+       int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive;
+       
+       if(!mode || !dpi_timing) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+       
+       PSB_DEBUG_ENTRY("pclk %d, hdisplay %d, hsync_start %d, hsync_end %d, htotal %d\n", 
+                                       mode->clock, mode->hdisplay, mode->hsync_start,
+                                       mode->hsync_end, mode->htotal);
+       PSB_DEBUG_ENTRY("vdisplay %d, vsync_start %d, vsync_end %d, vtotal %d\n", 
+                                       mode->vdisplay, mode->vsync_start,
+                                       mode->vsync_end, mode->vtotal);
+       
+       pclk_hactive = mode->hdisplay;
+       pclk_hfp = mode->hsync_start - mode->hdisplay;
+       pclk_hsync = mode->hsync_end - mode->hsync_start;
+       pclk_hbp = mode->htotal - mode->hsync_end;
+       
+       pclk_vactive = mode->vdisplay;
+       pclk_vfp = mode->vsync_start - mode->vdisplay;
+       pclk_vsync = mode->vsync_end - mode->vsync_start;
+       pclk_vbp = mode->vtotal - mode->vsync_end;
+       
+       /*
+        * byte clock counts were calculated by following formula
+        * bclock_count = pclk_count * bpp / num_lane / 8
+        */
+       dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp);
+       dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp);
+       dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp);
+       dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp);
+       dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp);
+       dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp);
+       dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp);
+
+       PSB_DEBUG_ENTRY("DPI timings: %d, %d, %d, %d, %d, %d, %d\n", 
+                                       dpi_timing->hsync_count, dpi_timing->hbp_count,
+                                       dpi_timing->hfp_count, dpi_timing->hactive_count,
+                                       dpi_timing->vsync_count, dpi_timing->vbp_count,
+                                       dpi_timing->vfp_count);
+                                       
+       return 0; 
+}
+
+void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+       struct drm_device * dev = dsi_config->dev;
+       int lane_count = dsi_config->lane_count;
+       struct mdfld_dsi_dpi_timing dpi_timing;
+       struct drm_display_mode * mode = dsi_config->mode;
+       u32 val = 0;
+       
+       PSB_DEBUG_ENTRY("Init DPI interface on pipe %d...\n", pipe);
+
+       /*un-ready device*/
+       REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0x00000000);
+       
+       /*init dsi adapter before kicking off*/
+       REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
+       
+       /*enable all interrupts*/
+       REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
+       
+       /*set up func_prg*/
+       val |= lane_count;
+       val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
+               
+       switch(dsi_config->bpp) {
+       case 16:
+               val |= DSI_DPI_COLOR_FORMAT_RGB565;
+               break;
+       case 18:
+               val |= DSI_DPI_COLOR_FORMAT_RGB666;
+               break;
+       case 24:
+               val |= DSI_DPI_COLOR_FORMAT_RGB888;
+               break;
+       default:
+               DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
+       }
+       REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val);
+       
+       REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe),
+                       (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
+       REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
+       
+       /*max value: 20 clock cycles of txclkesc*/
+       REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
+       
+       /*min 21 txclkesc, max: ffffh*/
+       REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xffff & DSI_RESET_TIMER_MASK);
+
+       REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), mode->vdisplay << 16 | mode->hdisplay);
+       
+       /*set DPI timing registers*/
+       mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
+       
+       REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_HBP_COUNT_REG(pipe), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_HFP_COUNT_REG(pipe), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_VBP_COUNT_REG(pipe), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_VFP_COUNT_REG(pipe), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
+       
+       REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46);
+       
+       /*min: 7d0 max: 4e20*/
+       REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0);
+       
+       /*set up video mode*/
+       val = 0;
+       val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
+       REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val);
+       
+       REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
+       
+       REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
+       
+       /*TODO: figure out how to setup these registers*/
+       if (get_panel_type(dev, pipe) == TC35876X)
+               REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
+       else
+               REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408);
+       
+       REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
+
+       if (get_panel_type(dev, pipe) == TC35876X)
+               tc35876x_set_bridge_reset_state(0);  /*Pull High Reset */
+
+       /*set device ready*/
+       REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0x00000001);
+}
+
+void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output * output, int pipe)
+{
+       struct drm_device * dev = output->dev;
+       /* struct drm_psb_private * dev_priv = dev->dev_private; */
+       
+       PSB_DEBUG_ENTRY("pipe %d panel state %d\n", pipe, output->panel_on);
+       
+       if(output->panel_on) 
+               return;
+               
+       /* clear special packet sent bit */
+       if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
+               REG_WRITE(MIPI_INTR_STAT_REG(pipe), DSI_INTR_STATE_SPL_PKG_SENT);
+               
+       /*send turn on package*/
+       REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON);
+       
+       /*wait for SPL_PKG_SENT interrupt*/
+       mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
+       
+       if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
+               REG_WRITE(MIPI_INTR_STAT_REG(pipe), DSI_INTR_STATE_SPL_PKG_SENT);
+
+       output->panel_on = 1;
+
+       /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+       /* if(pipe == 2) */
+       /*      dev_priv->dpi_panel_on2 = true; */
+       /* else if (pipe == 0) */
+       /*      dev_priv->dpi_panel_on = true; */
+}
+
+static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output * output, int pipe)
+{
+       struct drm_device * dev = output->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       /* struct drm_psb_private * dev_priv = dev->dev_private; */
+       
+       PSB_DEBUG_ENTRY("pipe %d panel state %d\n", pipe, output->panel_on);
+
+       /*if output is on, or mode setting didn't happen, ignore this*/
+       if((!output->panel_on) || output->first_boot) {
+               output->first_boot = 0; 
+               return;
+       }
+       
+       /* Wait for dpi fifo to empty */
+       mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
+
+       /* Clear the special packet interrupt bit if set */
+       if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
+               REG_WRITE(MIPI_INTR_STAT_REG(pipe), DSI_INTR_STATE_SPL_PKG_SENT);
+       
+       if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN) {
+               PSB_DEBUG_ENTRY("try to send the same package again, abort!");
+               goto shutdown_out;
+       }
+       
+       REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN);
+
+shutdown_out:
+       output->panel_on = 0;
+       output->first_boot = 0;
+       
+       /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+       /* if(pipe == 2) */
+       /*      dev_priv->dpi_panel_on2 = false; */
+       /* else if (pipe == 0) */
+       /*      dev_priv->dpi_panel_on = false;  */
+
+#ifdef CONFIG_PM_RUNTIME
+       if (drm_psb_ospm && !enable_gfx_rtpm) {
+//             pm_runtime_allow(&gpDrmDevice->pdev->dev);
+               schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000);
+       }
+
+       if (enable_gfx_rtpm)
+               pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay);
+#endif
+       return;
+}
+
+static void mdfld_dsi_dpi_set_power(struct drm_encoder * encoder, bool on)
+{
+       struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_dpi_output * dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+       int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
+       struct drm_device * dev = dsi_config->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       u32 pipeconf_reg = PIPEACONF;
+       
+       PSB_DEBUG_ENTRY("set power %s on pipe %d\n", on ? "On" : "Off", pipe);
+       
+       if (pipe)
+               pipeconf_reg = PIPECCONF;
+       
+       /*start up display island if it was shutdown*/
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON))
+               return;
+
+       if(on) {
+               if (get_panel_type(dev, pipe) == TMD_VID) {
+                       mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+               } else if (get_panel_type(dev, pipe) == TC35876X) {
+                       if (dsi_device_ready) {
+                               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+                               return;
+                       }
+
+                       mdfld_dsi_configure_up(dsi_encoder, pipe);
+                       dsi_device_ready = true;
+               } else {
+                       /*enable mipi port*/
+                       REG_WRITE(MIPI_PORT_CONTROL(pipe),
+                               REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31));
+                       REG_READ(MIPI_PORT_CONTROL(pipe));
+
+                       mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+                       mdfld_dsi_tpo_ic_init(dsi_config, pipe);
+               }
+
+               if(pipe == 2) {
+                       dev_priv->dpi_panel_on2 = true;
+               }
+               else {
+                       dev_priv->dpi_panel_on  = true;
+               }
+
+       } else {
+               if (get_panel_type(dev, pipe) == TMD_VID) {
+                       mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+               } else if (get_panel_type(dev, pipe) == TC35876X) {
+                       if (!dsi_device_ready) {
+                               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+                               return;
+                       }
+
+                       mdfld_dsi_configure_down(dsi_encoder, pipe);
+                       dsi_device_ready = false;
+               } else {
+                       mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+
+                       /*disable mipi port*/
+                       REG_WRITE(MIPI_PORT_CONTROL(pipe),
+                               REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31));
+                       REG_READ(MIPI_PORT_CONTROL(pipe));
+               }
+
+               if(pipe == 2) {
+                       dev_priv->dpi_panel_on2 = false;
+               }
+               else {
+                       dev_priv->dpi_panel_on  = false;
+               }
+
+       }
+       
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
+{
+       PSB_DEBUG_ENTRY("%s \n",  (mode == DRM_MODE_DPMS_ON ? "on":"off"));
+
+       if (mode == DRM_MODE_DPMS_ON) {
+               mdfld_dsi_dpi_set_power(encoder, true);
+               gbdispstatus = true;
+       } else {
+               mdfld_dsi_dpi_set_power(encoder, false);
+               gbdispstatus = false;
+#ifdef CONFIG_PM_RUNTIME
+               if (enable_gfx_rtpm)
+                       pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay);
+#endif
+       }
+
+       return;
+}
+
+bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder * encoder,
+                                    struct drm_display_mode * mode,
+                                    struct drm_display_mode * adjusted_mode)
+{
+       struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+       struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if(fixed_mode) {
+               adjusted_mode->hdisplay = fixed_mode->hdisplay;
+               adjusted_mode->hsync_start = fixed_mode->hsync_start;
+               adjusted_mode->hsync_end = fixed_mode->hsync_end;
+               adjusted_mode->htotal = fixed_mode->htotal;
+               adjusted_mode->vdisplay = fixed_mode->vdisplay;
+               adjusted_mode->vsync_start = fixed_mode->vsync_start;
+               adjusted_mode->vsync_end = fixed_mode->vsync_end;
+               adjusted_mode->vtotal = fixed_mode->vtotal;
+               adjusted_mode->clock = fixed_mode->clock;
+               drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+       }
+       
+       return true;
+}
+
+void mdfld_dsi_dpi_prepare(struct drm_encoder * encoder) 
+{
+       PSB_DEBUG_ENTRY("\n");
+       
+       mdfld_dsi_dpi_set_power(encoder, false);
+}
+
+void mdfld_dsi_dpi_commit(struct drm_encoder * encoder) 
+{
+       PSB_DEBUG_ENTRY("\n");
+       
+       mdfld_dsi_dpi_set_power(encoder, true);
+}
+
+/* For TC35876X */
+/* This functionality was implemented in FW in iCDK */
+/* But removed in DV0 and later. So need to add here. */
+static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+
+       printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+       REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
+       REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
+       REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0xffffff);
+       REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffffff);
+       REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14);
+       REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xff);
+       REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x25);
+       REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0xf0);
+       REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
+       REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
+       REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000820);
+       REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
+}
+
+static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config,
+                                       int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+       struct mdfld_dsi_dpi_timing dpi_timing;
+       struct drm_display_mode *mode = dsi_config->mode;
+
+       printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+       mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing,
+                                       dsi_config->lane_count,
+                                       dsi_config->bpp);
+
+       REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe),
+               mode->vdisplay << 16 | mode->hdisplay);
+       REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe),
+               dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_HBP_COUNT_REG(pipe),
+               dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_HFP_COUNT_REG(pipe),
+               dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe),
+               dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe),
+               dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_VBP_COUNT_REG(pipe),
+               dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
+       REG_WRITE(MIPI_VFP_COUNT_REG(pipe),
+               dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
+}
+
+static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+       int lane_count = dsi_config->lane_count;
+
+       printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+       if (pipe) {
+               REG_WRITE(MIPI_PORT_CONTROL(0), 0x00000002);
+               REG_WRITE(MIPI_PORT_CONTROL(2), 0x80000000);
+       } else {
+               REG_WRITE(MIPI_PORT_CONTROL(0), 0x80010000);
+               REG_WRITE(MIPI_PORT_CONTROL(2), 0x00);
+       }
+
+       REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150A600F);
+       REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), 0x0000000F);
+
+       /* lane_count = 3 */
+       REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), 0x00000200 | lane_count);
+
+       mdfld_mipi_set_video_timing(dsi_config, pipe);
+}
+
+static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+       struct drm_display_mode *mode = dsi_config->mode;
+
+       printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+       REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
+       REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
+       REG_WRITE(HSYNC_A,
+               ((mode->hsync_end - 1) << 16) | (mode->hsync_start - 1));
+
+       REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
+       REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
+       REG_WRITE(VSYNC_A,
+               ((mode->vsync_end - 1) << 16) | (mode->vsync_start - 1));
+
+       REG_WRITE(PIPEASRC,
+               ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+}
+/* End for TC35876X */
+
+void mdfld_dsi_dpi_mode_set(struct drm_encoder * encoder,
+                                  struct drm_display_mode * mode,
+                                  struct drm_display_mode * adjusted_mode)
+{
+       struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_dpi_output * dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+       struct drm_device * dev = dsi_config->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
+       
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dspcntr_reg = DSPACNTR;
+       
+       u32 pipeconf = dev_priv->pipeconf;
+       u32 dspcntr = dev_priv->dspcntr;
+       u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+       
+       PSB_DEBUG_ENTRY("set mode %dx%d on pipe %d", mode->hdisplay, mode->vdisplay, pipe);
+
+       if(pipe) {
+               pipeconf_reg = PIPECCONF;
+               dspcntr_reg = DSPCCNTR;
+       } else {
+               if (get_panel_type(dev, pipe) == TC35876X)
+                       mipi &= (~0x03); /* Use all four lanes */
+               else
+                       mipi |= 2;
+       }
+       
+       /*start up display island if it was shutdown*/
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON))
+               return;
+
+       if (get_panel_type(dev, pipe) == TC35876X) {
+               /*
+                * The following logic is required to reset the bridge and
+                * configure. This also starts the DSI clock at 200MHz.
+                */
+               int timeout = 0;
+
+               tc35876x_set_bridge_reset_state(0);  /*Pull High Reset */
+               tc35876x_toshiba_bridge_panel_on();
+               udelay(100);
+               /* Now start the DSI clock */
+               REG_WRITE(MRST_DPLL_A, 0x00);
+               REG_WRITE(MRST_FPA0, 0xC1);
+               REG_WRITE(MRST_DPLL_A, 0x00800000);
+               udelay(500);
+               REG_WRITE(MRST_DPLL_A, 0x80800000);
+               /*Wait for DSI PLL to lock */
+               while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+                       udelay(150);
+                       timeout++;
+               }
+               if (timeout == 20000)
+                       printk(KERN_ALERT "[DISPLAY] DSI PLL Locked timeout\n");
+               REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
+
+               mipi_set_properties(dsi_config, pipe);
+               mdfld_mipi_config(dsi_config, pipe);
+               mdfld_set_pipe_timing(dsi_config, pipe);
+
+               REG_WRITE(DSPABASE, 0x00);
+               REG_WRITE(DSPASTRIDE, (mode->hdisplay * 4));
+               REG_WRITE(DSPASIZE,
+                       ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+
+               REG_WRITE(DSPACNTR, 0x98000000);
+               REG_WRITE(DSPASURF, 0x00);
+
+               REG_WRITE(VGACNTRL, 0x80000000);
+               REG_WRITE(DEVICE_READY_REG, 0x00000001);
+
+               REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000);
+       }
+
+       /*set up mipi port FIXME: do at init time */
+       REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi);
+       REG_READ(MIPI_PORT_CONTROL(pipe));
+
+       if (get_panel_type(dev, pipe) == TMD_VID) {
+               /* NOP */
+       } else if (get_panel_type(dev, pipe) == TC35876X) {
+               /* set up DSI controller DPI interface */
+               mdfld_dsi_dpi_controller_init(dsi_config, pipe);
+
+               /* Configure MIPI Bridge and Panel */
+               tc35876x_configure_lvds_bridge(dev);
+               dsi_device_ready = true;
+               dev_priv->dpi_panel_on = true;
+       } else {
+               /*turn on DPI interface*/
+               mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+       }
+       
+       /*set up pipe*/
+       REG_WRITE(pipeconf_reg, pipeconf);
+       REG_READ(pipeconf_reg);
+       
+       /*set up display plane*/
+       REG_WRITE(dspcntr_reg, dspcntr);
+       REG_READ(dspcntr_reg);
+       
+       msleep(20); /* FIXME: this should wait for vblank */
+       
+       PSB_DEBUG_ENTRY("State %x, power %d\n", REG_READ(MIPI_INTR_STAT_REG(pipe)),
+                                       dpi_output->panel_on);
+
+       if (get_panel_type(dev, pipe) == TMD_VID) {
+               /* NOP */
+       } else if (get_panel_type(dev, pipe) == TC35876X) {
+               mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+       } else {
+               /* init driver ic */
+               mdfld_dsi_tpo_ic_init(dsi_config, pipe);
+               /*init backlight*/
+               mdfld_dsi_brightness_init(dsi_config, pipe);
+       }
+       
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+/*
+ * Init DSI DPI encoder. 
+ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
+ * return pointer of newly allocated DPI encoder, NULL on error
+ */ 
+struct mdfld_dsi_encoder * mdfld_dsi_dpi_init(struct drm_device * dev, 
+                               struct mdfld_dsi_connector * dsi_connector,
+                               struct panel_funcs* p_funcs)
+{
+       struct mdfld_dsi_dpi_output * dpi_output = NULL;
+       struct mdfld_dsi_config * dsi_config;
+       struct drm_connector * connector = NULL;
+       struct drm_encoder * encoder = NULL;
+       struct drm_display_mode * fixed_mode = NULL;
+       int pipe;
+       u32 data;
+       int ret;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if (!dsi_connector || !p_funcs) {
+               DRM_ERROR("Invalid parameters\n");
+               return NULL;
+       }
+
+       pipe = dsi_connector->pipe;
+
+       if (get_panel_type(dev, pipe) != TC35876X) {
+               dsi_config = mdfld_dsi_get_config(dsi_connector);
+
+               /* panel hard-reset */
+               if (p_funcs->reset) {
+                       ret = p_funcs->reset(pipe);
+                       if (ret) {
+                               DRM_ERROR("Panel %d hard-reset failed\n", pipe);
+                               return NULL;
+                       }
+               }
+
+               /* panel drvIC init */
+               if (p_funcs->drv_ic_init)
+                       p_funcs->drv_ic_init(dsi_config, pipe);
+
+               /* panel power mode detect */
+               ret = mdfld_dsi_get_power_mode(dsi_config, &data, false);
+               if (ret) {
+                       DRM_ERROR("Panel %d get power mode failed\n", pipe);
+                       dsi_connector->status = connector_status_disconnected;
+               } else {
+                       DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
+                       dsi_connector->status = connector_status_connected;
+               }
+       }
+
+       dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
+       if(!dpi_output) {
+               DRM_ERROR("No memory\n");
+               return NULL;
+       }
+       
+       if(dsi_connector->pipe) 
+               dpi_output->panel_on = 0;
+       else 
+               dpi_output->panel_on = 0;
+       
+       
+       dpi_output->dev = dev;
+       if (get_panel_type(dev, pipe) != TC35876X)
+               dpi_output->p_funcs = p_funcs;
+       dpi_output->first_boot = 1;
+       
+       /*get fixed mode*/
+       dsi_config = mdfld_dsi_get_config(dsi_connector);
+       fixed_mode = dsi_config->fixed_mode;
+       
+       /*create drm encoder object*/
+       connector = &dsi_connector->base.base;
+       encoder = &dpi_output->base.base;
+       drm_encoder_init(dev,
+                       encoder,
+                       p_funcs->encoder_funcs,
+                       DRM_MODE_ENCODER_LVDS);
+       drm_encoder_helper_add(encoder,
+                               p_funcs->encoder_helper_funcs);
+       
+       /*attach to given connector*/
+       drm_mode_connector_attach_encoder(connector, encoder);
+       
+       /*set possible crtcs and clones*/
+       if(dsi_connector->pipe) {
+               encoder->possible_crtcs = (1 << 2);
+               encoder->possible_clones = (1 << 1);
+       } else {
+               encoder->possible_crtcs = (1 << 0);
+               encoder->possible_clones = (1 << 0);
+       }
+
+       if (get_panel_type(dev, pipe) == TC35876X) {
+               struct drm_psb_private *dev_priv = dev->dev_private;
+               dev_priv->dpi_panel_on = false;
+       }
+
+       PSB_DEBUG_ENTRY("successfully\n");
+       
+       return &dpi_output->base;
+}
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dpi.h b/drivers/staging/mrst/drv/mdfld_dsi_dpi.h
new file mode 100644 (file)
index 0000000..8426f22
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DPI_H__
+#define __MDFLD_DSI_DPI_H__
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+struct mdfld_dsi_dpi_timing {
+       u16 hsync_count;
+       u16 hbp_count;
+       u16 hfp_count;
+       u16 hactive_count;
+       u16 vsync_count;
+       u16 vbp_count;
+       u16 vfp_count;
+};
+
+struct mdfld_dsi_dpi_output {
+       struct mdfld_dsi_encoder base;
+       struct drm_device *dev;
+       
+       int panel_on;
+       int first_boot;
+
+       struct panel_funcs *p_funcs;
+};
+
+#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
+
+/*export functions*/
+extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode * mode, 
+                                                                       struct mdfld_dsi_dpi_timing * dpi_timing,
+                                                                       int num_lane, int bpp);
+extern struct mdfld_dsi_encoder * mdfld_dsi_dpi_init(struct drm_device * dev, 
+                               struct mdfld_dsi_connector * dsi_connector,
+                               struct panel_funcs* p_funcs);
+                               
+/*MDFLD DPI helper functions*/
+extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
+extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder * encoder,
+                                    struct drm_display_mode * mode,
+                                    struct drm_display_mode * adjusted_mode);
+extern void mdfld_dsi_dpi_prepare(struct drm_encoder * encoder);
+extern void mdfld_dsi_dpi_commit(struct drm_encoder * encoder);
+extern void mdfld_dsi_dpi_mode_set(struct drm_encoder * encoder,
+                                  struct drm_display_mode * mode,
+                                  struct drm_display_mode * adjusted_mode);
+extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output * output,
+                                                               int pipe);
+extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe);
+#endif /*__MDFLD_DSI_DPI_H__*/
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_output.c b/drivers/staging/mrst/drv/mdfld_dsi_output.c
new file mode 100644 (file)
index 0000000..294c392
--- /dev/null
@@ -0,0 +1,1046 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include <linux/pm_runtime.h>
+#include <asm/intel_scu_ipc.h>
+
+#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
+
+/* get the CABC LABC from command line. */
+static int CABC_control = 1;
+static int LABC_control = 1;
+
+#ifdef MODULE
+module_param (CABC_control, int, 0644);
+module_param (LABC_control, int, 0644);
+#else
+static int __init parse_CABC_control(char *arg)
+{
+       /* CABC control can be passed in as a cmdline parameter */
+       /* to enable this feature add CABC=1 to cmdline */
+       /* to disable this feature add CABC=0 to cmdline */
+       if (!arg)
+               return -EINVAL;
+
+       if (!strcasecmp(arg, "0"))
+               CABC_control = 0;
+       else if (!strcasecmp (arg, "1"))
+               CABC_control = 1;
+
+       return 0;
+}
+early_param ("CABC", parse_CABC_control);
+
+static int __init parse_LABC_control(char *arg)
+{
+       /* LABC control can be passed in as a cmdline parameter */
+       /* to enable this feature add LABC=1 to cmdline */
+       /* to disable this feature add LABC=0 to cmdline */
+       if (!arg)
+               return -EINVAL;
+
+       if (!strcasecmp(arg, "0"))
+               LABC_control = 0;
+       else if (!strcasecmp (arg, "1"))
+               LABC_control = 1;
+
+       return 0;
+}
+early_param ("LABC", parse_LABC_control);
+#endif
+
+/**
+ * make these MCS command global 
+ * we don't need 'movl' everytime we send them.
+ * FIXME: these datas were provided by OEM, we should get them from GCT.
+ **/
+/* FIXME: make the below data u8 instead of u32; note byte order! */
+static u32 mdfld_dbi_mcs_hysteresis[] = {
+       0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff, 
+       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 
+       0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
+       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 
+       0x000000ff,
+};
+
+static u32 mdfld_dbi_mcs_display_profile[] = {
+       0x50281450, 0x0000c882, 0x00000000, 0x00000000,
+       0x00000000,
+};
+
+static u32 mdfld_dbi_mcs_kbbc_profile[] = {
+       0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
+}; 
+       
+static u32 mdfld_dbi_mcs_gamma_profile[] = {
+       0x81111158, 0x88888888, 0x88888888,
+}; 
+
+/**
+ * Check and see if the generic control or data buffer is empty and ready.
+ */
+void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
+{
+       u32 GEN_BF_time_out_count = 0;
+       
+       /* Check MIPI Adatper command registers */
+       for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
+       {
+               if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
+                       break;
+               udelay (100);
+       }
+
+       if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
+               DRM_ERROR("mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n", gen_fifo_stat_reg);
+}
+
+/**
+ * Manage the DSI MIPI keyboard and display brightness.
+ * FIXME: this is exported to OSPM code. should work out an specific 
+ * display interface to OSPM. 
+ */
+#define PWM0_CLK_DIV   64000
+#define PWM0CLKDIV0    0x62
+#define PWM0CLKDIV1    0x61
+static void tc35876x_brightness_init(struct mdfld_dsi_config *dsi_config,
+                               int pipe)
+{
+       int ret;
+
+       printk(KERN_ALERT "[DISPLAY] %s\n", __func__);
+
+       /* Set PWM frequency to 300 Hz = (19.2*1000*1000)/64000 */
+       ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, PWM0_CLK_DIV & 0xff);
+       ret |= intel_scu_ipc_iowrite8(PWM0CLKDIV1, (PWM0_CLK_DIV >> 8) & 0xff);
+       if (ret)
+               printk(KERN_ERR "[DISPLAY] %s: ipc write fail\n", __func__);
+}
+
+void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe)
+{
+       struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+       struct drm_device * dev = sender->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       u32 gen_ctrl_val;
+
+       if (get_panel_type(dev, pipe) == TC35876X) {
+               tc35876x_brightness_init(dsi_config, pipe);
+               return;
+       }
+
+       if(!sender) {
+               DRM_ERROR("No sender found\n");
+       }
+       /* Set default display backlight value to 85% (0xd8)*/
+       mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1,
+                               true);
+                                   
+       /* Set minimum brightness setting of CABC function to 20% (0x33)*/
+       mdfld_dsi_send_mcs_short(sender, write_cabc_min_bright, 0x33, 1, true);
+
+       /* FIXME: make the below data u8 instead of u32; note byte order! */
+
+       /* write hysteresis values */
+       mdfld_dsi_send_mcs_long(sender, (u8 *) mdfld_dbi_mcs_hysteresis,
+                               sizeof(mdfld_dbi_mcs_hysteresis), true);
+       /* write display profile values */
+       mdfld_dsi_send_mcs_long(sender, (u8 *) mdfld_dbi_mcs_display_profile,
+                               sizeof(mdfld_dbi_mcs_display_profile), true);
+       /* write KBBC profile values */
+       mdfld_dsi_send_mcs_long(sender, (u8 *) mdfld_dbi_mcs_kbbc_profile,
+                               sizeof(mdfld_dbi_mcs_kbbc_profile), true);
+       /* write gamma setting */
+       mdfld_dsi_send_mcs_long(sender, (u8 *) mdfld_dbi_mcs_gamma_profile,
+                               sizeof(mdfld_dbi_mcs_gamma_profile), true);
+       
+       /* Enable backlight or/and LABC */
+       gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
+       if (LABC_control == 1 || CABC_control == 1)
+               gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
+
+       if (LABC_control == 1)
+               gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
+
+       dev_priv->mipi_ctrl_display = gen_ctrl_val;
+       
+       mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val,
+                               1, true);
+
+       if (CABC_control == 0)
+               return;
+
+       mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true);
+}
+
+/**
+ * Manage the mipi display brightness.
+ * TODO: refine this interface later
+ */
+#define BACKLIGHT_DUTY_FACTOR          0x63
+#define MIN_BACKLIGHT_DUTY_FACTOR      0x10
+#define PWM0DUTYCYCLE                  0x67
+static void tc35876x_brightness_control(struct drm_device *dev, int pipe,
+                                       int level)
+{
+       int ret;
+       int duty_val;
+
+       duty_val = min(MIN_BACKLIGHT_DUTY_FACTOR,
+               level * BACKLIGHT_DUTY_FACTOR / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
+
+       printk(KERN_ALERT "[DISPLAY] %s: level = %d, duty_val = %d\n", __func__,
+               level, duty_val);
+
+       ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
+       if (ret)
+               printk(KERN_ERR "[DISPLAY] %s: ipc write fail\n", __func__);
+}
+
+void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level)
+{
+       struct mdfld_dsi_pkg_sender * sender;
+       struct drm_psb_private * dev_priv;
+       struct mdfld_dsi_config * dsi_config;
+       u32 gen_ctrl_val = 0;
+       enum panel_type p_type = TMD_VID;
+
+       if (get_panel_type(dev, pipe) == TC35876X) {
+               tc35876x_brightness_control(dev, pipe, level);
+               return;
+       }
+
+       if(!dev || (pipe != 0 && pipe != 2)) {
+               DRM_ERROR("Invalid parameter\n");
+               return;
+       }
+
+       p_type = get_panel_type(dev, 0);
+
+       dev_priv = dev->dev_private;
+
+       if(pipe)
+               dsi_config = dev_priv->dsi_configs[1];
+       else
+               dsi_config = dev_priv->dsi_configs[0];
+
+       sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+       if(!sender) {
+               DRM_ERROR("No sender found\n");
+               return;
+       }
+
+       gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
+
+       PSB_DEBUG_ENTRY("pipe = %d, gen_ctrl_val = %d.  \n", pipe, gen_ctrl_val);
+
+       if(p_type == TMD_VID || p_type == TMD_CMD){
+               /* Set display backlight value */
+               mdfld_dsi_send_mcs_short(sender, tmd_write_display_brightness,
+                                       (u8)gen_ctrl_val, 1, true);
+       } else {
+               /* Set display backlight value */
+               mdfld_dsi_send_mcs_short(sender, write_display_brightness,
+                                       (u8)gen_ctrl_val, 1, true);
+
+               /* Enable backlight control */
+               if (level == 0)
+                       gen_ctrl_val = 0;
+               else
+                       gen_ctrl_val = dev_priv->mipi_ctrl_display;
+
+               mdfld_dsi_send_mcs_short(sender, write_ctrl_display,
+                                       (u8)gen_ctrl_val, 1, true);
+       }
+}
+
+/*
+ * shut down DSI controller
+ */ 
+static void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+       struct drm_device * dev;
+       int retry = 100;
+       
+       PSB_DEBUG_ENTRY("shutting down DSI controller on pipe %d... dsi_config %p\n", pipe, dsi_config);
+       
+       if(!dsi_config) {
+               DRM_ERROR("Invalid parameter\n");
+               return;
+       }
+       
+       dev = dsi_config->dev;
+       
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+               DRM_ERROR("hw begin failed\n");
+               return;
+       }
+               
+       if (!(REG_READ(MIPI_DEVICE_READY_REG(pipe)) &  DSI_DEVICE_READY))
+               goto shutdown_out;
+       
+       /*send shut down package, clean packet send bit first*/
+       if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) {
+               REG_WRITE(MIPI_INTR_STAT_REG(pipe),
+                       (REG_READ(MIPI_INTR_STAT_REG(pipe)) | DSI_INTR_STATE_SPL_PKG_SENT));
+       }
+       
+       /*send shut down package in HS*/
+       REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN);
+       
+       
+       /*
+        * make sure shut down is sent.
+        * FIXME: add max retry counter
+        */
+       while (!(REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)) {
+               retry--;
+               
+               if(!retry) {
+                       PSB_DEBUG_ENTRY("timeout\n");
+                       break;
+               }
+       }
+       
+       /*sleep 1 ms to ensure shutdown finished*/
+       msleep(100);
+       
+       /*un-ready device*/
+       REG_WRITE(MIPI_DEVICE_READY_REG(pipe),
+               (REG_READ(MIPI_DEVICE_READY_REG(pipe)) & ~DSI_DEVICE_READY));
+
+shutdown_out:                     
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+       struct drm_device * dev;
+       int retry = 100;
+       
+       PSB_DEBUG_ENTRY("starting up DSI controller on pipe %d...\n", pipe);
+       
+       if(!dsi_config) {
+               DRM_ERROR("Invalid parameter\n");
+               return;
+       }
+       
+       dev = dsi_config->dev;
+       
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+               DRM_ERROR("hw begin failed\n");
+               return;
+       }
+       
+       if ((REG_READ(MIPI_DEVICE_READY_REG(pipe)) & DSI_DEVICE_READY))
+               goto startup_out;
+       
+       /*if config DPI, turn on DPI interface*/
+       if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+               if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) {
+                       REG_WRITE(MIPI_INTR_STAT_REG(pipe), DSI_INTR_STATE_SPL_PKG_SENT);
+               }
+               
+               REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON);
+               
+               /*
+                * make sure shut down is sent.
+                * FIXME: add max retry counter
+                */
+               while (!(REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)) {
+                       retry--;
+                       if(!retry) {
+                               PSB_DEBUG_ENTRY("timeout\n");
+                               break;
+                       }
+               }
+               
+               msleep(100);
+       }
+       
+       /*set device ready*/
+       REG_WRITE(MIPI_DEVICE_READY_REG(pipe),
+               REG_READ(MIPI_DEVICE_READY_REG(pipe)) | DSI_DEVICE_READY);
+
+startup_out:   
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
+                               u8 dcs, u32 *data, bool hs)
+{
+       struct mdfld_dsi_pkg_sender *sender
+               = mdfld_dsi_get_pkg_sender(dsi_config);
+
+       if (!sender || !data) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       return mdfld_dsi_read_mcs(sender, dcs, data, 1, hs);
+}
+
+int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode,
+                       bool hs)
+{
+       if (!dsi_config || !mode) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, hs);
+}
+
+int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
+                               u32 *result, bool hs)
+{
+       if (!dsi_config || !result) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result, hs);
+}
+
+/*
+ * NOTE: this function was used by OSPM.
+ * TODO: will be removed later, should work out display interfaces for OSPM
+ */
+void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+       if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
+               DRM_ERROR("Invalid parameters\n");
+               return;
+       }
+       
+       if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+               mdfld_dsi_dpi_controller_init(dsi_config, pipe);
+       else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+               mdfld_dsi_controller_dbi_init(dsi_config, pipe);
+       else
+               DRM_ERROR("Bad DSI encoder type\n");
+}
+
+static void mdfld_dsi_connector_save(struct drm_connector * connector)
+{
+       PSB_DEBUG_ENTRY("\n");
+}
+
+static void mdfld_dsi_connector_restore(struct drm_connector * connector)
+{
+       PSB_DEBUG_ENTRY("\n");
+}
+
+/* FIXME: start using the force parameter */
+static enum drm_connector_status
+mdfld_dsi_connector_detect(struct drm_connector *connector, bool force)
+{
+       struct psb_intel_output *psb_output
+               = to_psb_intel_output(connector);
+       struct mdfld_dsi_connector *dsi_connector
+               = MDFLD_DSI_CONNECTOR(psb_output);
+
+       PSB_DEBUG_ENTRY("\n");
+
+       return dsi_connector->status;
+}
+
+static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
+                                                                                       struct drm_property * property,
+                                                                                       uint64_t value)
+{
+       struct drm_encoder * encoder = connector->encoder;
+       struct backlight_device * psb_bd;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if (!strcmp(property->name, "scaling mode") && encoder) {
+               struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
+               bool bTransitionFromToCentered;
+               uint64_t curValue;
+
+               if (!psb_crtc)
+                       goto set_prop_error;
+
+               switch (value) {
+               case DRM_MODE_SCALE_FULLSCREEN:
+                       break;
+               case DRM_MODE_SCALE_NO_SCALE:
+                       break;
+               case DRM_MODE_SCALE_ASPECT:
+                       break;
+               default:
+                       goto set_prop_error;
+               }
+
+               if (drm_connector_property_get_value(connector, property, &curValue))
+                       goto set_prop_error;
+
+               if (curValue == value)
+                       goto set_prop_done;
+
+               if (drm_connector_property_set_value(connector, property, value))
+                       goto set_prop_error;
+
+               bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
+                       (value == DRM_MODE_SCALE_NO_SCALE);
+
+               if (psb_crtc->saved_mode.hdisplay != 0 &&
+                   psb_crtc->saved_mode.vdisplay != 0) {
+                       if (bTransitionFromToCentered) {
+                               if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
+                                           encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
+                                       goto set_prop_error;
+                       } else {
+                               struct drm_encoder_helper_funcs *pEncHFuncs  = encoder->helper_private;
+                               pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
+                                                    &psb_crtc->saved_adjusted_mode);
+                       }
+               }
+       } else if (!strcmp(property->name, "backlight") && encoder) {
+               PSB_DEBUG_ENTRY("backlight level = %d\n", (int)value);
+               if (drm_connector_property_set_value(connector, property, value))
+                       goto set_prop_error;
+               else {
+                       PSB_DEBUG_ENTRY("set brightness to %d", (int)value);
+                       psb_bd = psb_get_backlight_device();
+                       if(psb_bd) {
+                               psb_bd->props.brightness = value;
+                               psb_set_brightness(psb_bd);
+                       }
+               }
+       } 
+set_prop_done:
+    return 0;
+set_prop_error:
+    return -1;
+}
+
+static void mdfld_dsi_connector_destroy(struct drm_connector * connector)
+{
+       struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+       struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+       struct mdfld_dsi_pkg_sender * sender;
+       
+       PSB_DEBUG_ENTRY("\n");
+       
+       if(!dsi_connector) {
+               return;
+       }
+       
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
+       
+       sender = dsi_connector->pkg_sender;
+       
+       mdfld_dsi_pkg_sender_destroy(sender);
+       
+       kfree(dsi_connector);
+}
+
+static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
+{
+       struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+       struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+       struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+       struct drm_display_mode * dup_mode = NULL;
+       struct drm_device * dev = connector->dev;
+       
+       PSB_DEBUG_ENTRY("\n");
+
+       connector->display_info.min_vfreq = 0;
+       connector->display_info.max_vfreq = 200;
+       connector->display_info.min_hfreq = 0;
+       connector->display_info.max_hfreq = 200;
+
+       if(fixed_mode) {
+               PSB_DEBUG_ENTRY("fixed_mode %dx%d\n", fixed_mode->hdisplay, fixed_mode->vdisplay);
+               
+               dup_mode = drm_mode_duplicate(dev, fixed_mode);
+               drm_mode_probed_add(connector, dup_mode);
+               return 1;
+       }
+       
+       DRM_ERROR("Didn't get any modes!\n");
+       
+       return 0;
+}
+
+static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
+{
+       struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+       struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+       struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+
+       PSB_DEBUG_ENTRY("mode %p, fixed mode %p\n", mode, fixed_mode);
+
+       if(mode->flags & DRM_MODE_FLAG_DBLSCAN) 
+               return MODE_NO_DBLESCAN;
+
+       if(mode->flags & DRM_MODE_FLAG_INTERLACE)
+               return MODE_NO_INTERLACE;
+
+       /**
+        * FIXME: current DC has no fitting unit, reject any mode setting request
+        * will figure out a way to do up-scaling(pannel fitting) later.  
+        **/
+       if(fixed_mode) {
+               if(mode->hdisplay != fixed_mode->hdisplay)
+                       return MODE_PANEL;
+
+               if(mode->vdisplay != fixed_mode->vdisplay)
+                       return MODE_PANEL;
+       }
+
+       PSB_DEBUG_ENTRY("ok\n");
+
+       return MODE_OK;
+}
+
+static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
+{
+#ifdef CONFIG_PM_RUNTIME
+       struct drm_device * dev = connector->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       bool panel_on, panel_on2;
+#endif
+
+       if (mode == connector->dpms)
+               return;
+
+       /*first, execute dpms*/
+               
+       drm_helper_connector_dpms(connector, mode);
+       
+#ifdef CONFIG_PM_RUNTIME       
+       if(is_panel_vid_or_cmd(dev)) {
+               /*DPI panel*/
+               panel_on = dev_priv->dpi_panel_on;
+               panel_on2 = dev_priv->dpi_panel_on2;
+       } else {
+               /*DBI panel*/
+               panel_on = dev_priv->dbi_panel_on;
+               panel_on2 = dev_priv->dbi_panel_on2;
+       }       
+       
+       /*then check all display panels + monitors status*/
+       /* Make sure that the Display (B) sub-system status isn't i3 when
+        * R/W the DC register, otherwise "Fabric error" issue would occur
+        * during S0i3 state. */
+       if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN)) {
+               /*request rpm idle*/
+               if(dev_priv->rpm_enabled) {
+                       pm_request_idle(&dev->pdev->dev);
+               }
+       } 
+       
+       /**
+        * if rpm wasn't enabled yet, try to allow it
+        * FIXME: won't enable rpm for DPI since DPI
+        * CRTC setting is a little messy now. 
+        * Enable it later!
+        */
+#if 0
+       if(!dev_priv->rpm_enabled && !is_panel_vid_or_cmd(dev))
+               ospm_runtime_pm_allow(dev);
+#endif
+#endif
+}
+
+static struct drm_encoder * mdfld_dsi_connector_best_encoder(struct drm_connector * connector) 
+{
+       struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+       struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+       struct mdfld_dsi_encoder * encoder = NULL;
+       
+       PSB_DEBUG_ENTRY("config type %d\n", dsi_config->type);
+       
+       if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) 
+               encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
+       else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) 
+               encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
+       
+       PSB_DEBUG_ENTRY("get encoder %p\n", encoder);
+       
+       if(!encoder) {
+               DRM_ERROR("Invalid encoder for type %d\n", dsi_config->type);
+               return NULL;
+       }
+       
+       dsi_config->encoder = encoder;  
+               
+       return &encoder->base;  
+}
+
+/*DSI connector funcs*/
+static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
+       .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
+       .save = mdfld_dsi_connector_save,
+       .restore = mdfld_dsi_connector_restore,
+       .detect = mdfld_dsi_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .set_property = mdfld_dsi_connector_set_property,
+       .destroy = mdfld_dsi_connector_destroy,
+};
+
+/*DSI connector helper funcs*/
+static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
+       .get_modes = mdfld_dsi_connector_get_modes,
+       .mode_valid = mdfld_dsi_connector_mode_valid,
+       .best_encoder = mdfld_dsi_connector_best_encoder,
+};
+
+static int mdfld_dsi_get_default_config(struct drm_device * dev, 
+                                                                               struct mdfld_dsi_config * config, int pipe)
+{
+       if(!dev || !config) {
+               DRM_ERROR("Invalid parameters");
+               return -EINVAL;
+       }
+       
+       config->bpp = 24;
+       config->type = is_panel_vid_or_cmd(dev);
+       if (get_panel_type(dev, pipe) == TC35876X)
+               config->lane_count = 4;
+       else
+               config->lane_count = 2;
+       config->channel_num = 0;
+       /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
+       if (get_panel_type(dev, pipe) == TMD_VID) {
+               config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
+       } else if (get_panel_type(dev, pipe) == TC35876X) {
+               config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS;
+       } else {
+               config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
+       }
+       
+       return 0;
+}
+
+/*
+ * Returns the panel fixed mode from configuration. 
+ */
+static struct drm_display_mode *
+mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+       struct drm_display_mode *mode;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+       bool use_gct = false;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+       if (!mode)
+               return NULL;
+
+       if (use_gct) {
+               PSB_DEBUG_ENTRY("gct find MIPI panel. \n");
+
+               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+               mode->hsync_start = mode->hdisplay + \
+                               ((ti->hsync_offset_hi << 8) | \
+                               ti->hsync_offset_lo);
+               mode->hsync_end = mode->hsync_start + \
+                               ((ti->hsync_pulse_width_hi << 8) | \
+                               ti->hsync_pulse_width_lo);
+               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+                                                               ti->hblank_lo);
+               mode->vsync_start = \
+                       mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+                                               ti->vsync_offset_lo);
+               mode->vsync_end = \
+                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+                                               ti->vsync_pulse_width_lo);
+               mode->vtotal = mode->vdisplay + \
+                               ((ti->vblank_hi << 8) | ti->vblank_lo);
+               mode->clock = ti->pixel_clock * 10;
+
+               PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay);
+               PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay);
+               PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start);
+               PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end);
+               PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal);
+               PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start);
+               PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end);
+               PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal);
+               PSB_DEBUG_ENTRY("clock is %d\n", mode->clock);
+       } else {
+               if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { 
+                       if (get_panel_type(dev, pipe) == TMD_VID) {
+                               mode->hdisplay = 480;
+                               mode->vdisplay = 854;
+                               mode->hsync_start = 487;
+                               mode->hsync_end = 490;
+                               mode->htotal = 499;
+                               mode->vsync_start = 861;
+                               mode->vsync_end = 865;
+                               mode->vtotal = 873;
+                               mode->clock = 33264;
+                       } else {
+                               mode->hdisplay = 864;
+                               mode->vdisplay = 480;
+                               mode->hsync_start = 873;
+                               mode->hsync_end = 876;
+                               mode->htotal = 887;
+                               mode->vsync_start = 487;
+                               mode->vsync_end = 490;
+                               mode->vtotal = 499;
+                               mode->clock = 33264;
+                       }
+               } else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+                       mode->hdisplay = 864;
+                       mode->vdisplay = 480;
+                       mode->hsync_start = 872;
+                       mode->hsync_end = 876;
+                       mode->htotal = 884;
+                       mode->vsync_start = 482;
+                       mode->vsync_end = 494;
+                       mode->vtotal = 486;
+                       mode->clock = 25777;
+                       
+               }
+       }
+
+       drm_mode_set_name(mode);
+       drm_mode_set_crtcinfo(mode, 0);
+       
+       mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+       return mode;
+}
+
+int mdfld_dsi_panel_reset(int pipe)
+{
+       unsigned gpio;
+       int ret = 0;
+
+       switch (pipe) {
+       case 0:
+               gpio = 128;
+               break;
+       case 2:
+               gpio = 34;
+               break;
+       default:
+               DRM_ERROR("Invalid output\n");
+               return -EINVAL;
+       }
+
+       ret = gpio_request(gpio, "gfx");
+       if (ret) {
+               DRM_ERROR("gpio_rqueset failed\n");
+               return ret;
+       }
+
+       ret = gpio_direction_output(gpio, 1);
+       if (ret) {
+               DRM_ERROR("gpio_direction_output failed\n");
+               goto gpio_error;
+       }
+
+       gpio_get_value(128);
+
+gpio_error:
+       if (gpio_is_valid(gpio))
+               gpio_free(gpio);
+
+       PSB_DEBUG_ENTRY("Panel reset done\n");
+
+       return ret;
+}
+
+/*
+ * MIPI output init
+ * @dev drm device
+ * @pipe pipe number. 0 or 2
+ * @config 
+ * 
+ * Do the initialization of a MIPI output, including create DRM mode objects
+ * initialization of DSI output on @pipe 
+ */
+void mdfld_dsi_output_init(struct drm_device * dev,
+                          int pipe, 
+                          struct mdfld_dsi_config * config,
+                          struct panel_funcs* p_cmd_funcs,
+                          struct panel_funcs* p_vid_funcs)
+{
+       struct mdfld_dsi_config * dsi_config;
+       struct mdfld_dsi_connector * dsi_connector;
+       struct psb_intel_output * psb_output;
+       struct drm_connector * connector;
+       struct mdfld_dsi_encoder * encoder;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct panel_info dsi_panel_info;
+       u32 width_mm, height_mm;
+
+       PSB_DEBUG_ENTRY("init DSI output on pipe %d\n", pipe);
+       
+       if(!dev || ((pipe != 0) && (pipe != 2))) {
+               DRM_ERROR("Invalid parameter\n");
+               return;
+       }
+       
+       /*create a new connetor*/
+       dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
+       if(!dsi_connector) {
+               DRM_ERROR("No memory");
+               return;
+       }
+       
+       dsi_connector->pipe =  pipe;
+       
+       /*set DSI config*/
+       if(config) { 
+               dsi_config = config;
+       } else {
+               dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
+               if(!dsi_config) {
+                       DRM_ERROR("cannot allocate memory for DSI config\n");
+                       goto dsi_init_err0;
+               }
+               
+               mdfld_dsi_get_default_config(dev, dsi_config, pipe);
+       }
+       
+       dsi_connector->private = dsi_config;
+       
+       dsi_config->changed = 1;
+       dsi_config->dev = dev;
+       
+       /*init fixed mode basing on DSI config type*/
+       if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+               dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
+               if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
+                       goto dsi_init_err0;
+       } else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+               dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
+               if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
+                       goto dsi_init_err0;
+       }
+
+       width_mm = dsi_panel_info.width_mm;
+       height_mm = dsi_panel_info.height_mm;
+
+       dsi_config->mode = dsi_config->fixed_mode;
+       dsi_config->connector = dsi_connector;
+       
+       if(!dsi_config->fixed_mode) {
+               DRM_ERROR("No pannel fixed mode was found\n");
+               goto dsi_init_err0;
+       }
+       
+       if(pipe && dev_priv->dsi_configs[0]) {
+               dsi_config->dvr_ic_inited = 0;
+               dev_priv->dsi_configs[1] = dsi_config;
+       } else if(pipe == 0) {
+               dsi_config->dvr_ic_inited = 1;
+               dev_priv->dsi_configs[0] = dsi_config;
+       } else {
+               DRM_ERROR("Trying to init MIPI1 before MIPI0\n");
+               goto dsi_init_err0;
+       }
+
+       /*init drm connector object*/
+       psb_output = &dsi_connector->base;
+       
+       psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
+
+       connector = &psb_output->base;
+       drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
+       drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
+       
+       connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+       connector->display_info.width_mm = width_mm;
+       connector->display_info.height_mm = height_mm;
+       connector->interlace_allowed = false;
+       connector->doublescan_allowed = false;
+       
+       /*attach properties*/
+       drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
+       drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
+
+       /*init DSI package sender on this output*/
+       if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
+               DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
+               goto dsi_init_err0;
+       }
+
+       /*create DBI & DPI encoders*/
+       if(p_cmd_funcs) {
+               encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
+               if(!encoder) {
+                       DRM_ERROR("Create DBI encoder failed\n");
+                       goto dsi_init_err1;
+               }
+               encoder->private = dsi_config;
+               dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
+       }
+       
+       if(p_vid_funcs) {
+               encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
+               if(!encoder) {
+                       DRM_ERROR("Create DPI encoder failed\n");
+                       goto dsi_init_err1;
+               }
+               encoder->private = dsi_config;
+               dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
+       }
+       
+       drm_sysfs_connector_add(connector);
+       
+       PSB_DEBUG_ENTRY("successfully\n");
+       return;
+       
+       /*TODO: add code to destroy outputs on error*/
+dsi_init_err1:
+       /*destroy sender*/
+       mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
+
+       drm_connector_cleanup(connector);
+       
+       if(dsi_config->fixed_mode)
+               kfree(dsi_config->fixed_mode);
+       if(dsi_config) 
+               kfree(dsi_config);
+dsi_init_err0:
+       if(dsi_connector) {
+               kfree(dsi_connector);
+       }
+}
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_output.h b/drivers/staging/mrst/drv/mdfld_dsi_output.h
new file mode 100644 (file)
index 0000000..c6c2317
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_OUTPUT_H__
+#define __MDFLD_DSI_OUTPUT_H__
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+#include "mdfld_output.h"
+
+#include <asm/mrst.h>
+
+
+#ifdef DEBUG
+#define CHECK_PIPE(pipe) ({                    \
+       const typeof(pipe) __pipe = (pipe);     \
+       BUG_ON(__pipe != 0 && __pipe != 2);     \
+       __pipe; })
+#else
+#define CHECK_PIPE(pipe) (pipe)
+#endif
+
+/*
+ * Actual MIPIA->MIPIC reg offset is 0x800, value 0x400 is valid for 0 and 2
+ */
+#define REG_OFFSET(pipe) (CHECK_PIPE(pipe) * 0x400)
+
+/* mdfld DSI controller registers */
+#define MIPI_DEVICE_READY_REG(pipe)            (0xb000 + REG_OFFSET(pipe))
+#define MIPI_INTR_STAT_REG(pipe)               (0xb004 + REG_OFFSET(pipe))
+#define MIPI_INTR_EN_REG(pipe)                 (0xb008 + REG_OFFSET(pipe))
+#define MIPI_DSI_FUNC_PRG_REG(pipe)            (0xb00c + REG_OFFSET(pipe))
+#define MIPI_HS_TX_TIMEOUT_REG(pipe)           (0xb010 + REG_OFFSET(pipe))
+#define MIPI_LP_RX_TIMEOUT_REG(pipe)           (0xb014 + REG_OFFSET(pipe))
+#define MIPI_TURN_AROUND_TIMEOUT_REG(pipe)     (0xb018 + REG_OFFSET(pipe))
+#define MIPI_DEVICE_RESET_TIMER_REG(pipe)      (0xb01c + REG_OFFSET(pipe))
+#define MIPI_DPI_RESOLUTION_REG(pipe)          (0xb020 + REG_OFFSET(pipe))
+#define MIPI_DBI_FIFO_THROTTLE_REG(pipe)       (0xb024 + REG_OFFSET(pipe))
+#define MIPI_HSYNC_COUNT_REG(pipe)             (0xb028 + REG_OFFSET(pipe))
+#define MIPI_HBP_COUNT_REG(pipe)               (0xb02c + REG_OFFSET(pipe))
+#define MIPI_HFP_COUNT_REG(pipe)               (0xb030 + REG_OFFSET(pipe))
+#define MIPI_HACTIVE_COUNT_REG(pipe)           (0xb034 + REG_OFFSET(pipe))
+#define MIPI_VSYNC_COUNT_REG(pipe)             (0xb038 + REG_OFFSET(pipe))
+#define MIPI_VBP_COUNT_REG(pipe)               (0xb03c + REG_OFFSET(pipe))
+#define MIPI_VFP_COUNT_REG(pipe)               (0xb040 + REG_OFFSET(pipe))
+#define MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe)   (0xb044 + REG_OFFSET(pipe))
+#define MIPI_DPI_CONTROL_REG(pipe)             (0xb048 + REG_OFFSET(pipe))
+#define MIPI_DPI_DATA_REG(pipe)                        (0xb04c + REG_OFFSET(pipe))
+#define MIPI_INIT_COUNT_REG(pipe)              (0xb050 + REG_OFFSET(pipe))
+#define MIPI_MAX_RETURN_PACK_SIZE_REG(pipe)    (0xb054 + REG_OFFSET(pipe))
+#define MIPI_VIDEO_MODE_FORMAT_REG(pipe)       (0xb058 + REG_OFFSET(pipe))
+#define MIPI_EOT_DISABLE_REG(pipe)             (0xb05c + REG_OFFSET(pipe))
+#define MIPI_LP_BYTECLK_REG(pipe)              (0xb060 + REG_OFFSET(pipe))
+#define MIPI_LP_GEN_DATA_REG(pipe)             (0xb064 + REG_OFFSET(pipe))
+#define MIPI_HS_GEN_DATA_REG(pipe)             (0xb068 + REG_OFFSET(pipe))
+#define MIPI_LP_GEN_CTRL_REG(pipe)             (0xb06c + REG_OFFSET(pipe))
+#define MIPI_HS_GEN_CTRL_REG(pipe)             (0xb070 + REG_OFFSET(pipe))
+#define MIPI_GEN_FIFO_STAT_REG(pipe)           (0xb074 + REG_OFFSET(pipe))
+#define MIPI_HS_LS_DBI_ENABLE_REG(pipe)                (0xb078 + REG_OFFSET(pipe))
+#define MIPI_DPHY_PARAM_REG(pipe)              (0xb080 + REG_OFFSET(pipe))
+#define MIPI_DBI_BW_CTRL_REG(pipe)             (0xb084 + REG_OFFSET(pipe))
+#define MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe)        (0xb088 + REG_OFFSET(pipe))
+
+#define MIPI_CTRL_REG(pipe)                    (0xb104 + REG_OFFSET(pipe))
+#define MIPI_DATA_ADD_REG(pipe)                        (0xb108 + REG_OFFSET(pipe))
+#define MIPI_DATA_LEN_REG(pipe)                        (0xb10c + REG_OFFSET(pipe))
+#define MIPI_CMD_ADD_REG(pipe)                 (0xb110 + REG_OFFSET(pipe))
+#define MIPI_CMD_LEN_REG(pipe)                 (0xb114 + REG_OFFSET(pipe))
+
+/* non-uniform reg offset */
+#define MIPI_PORT_CONTROL(pipe)                (CHECK_PIPE(pipe) ? MIPI_C : MIPI)
+
+#define DSI_DEVICE_READY                                       (0x1)
+#define DSI_POWER_STATE_ULPS_ENTER                     (0x2 << 1)
+#define DSI_POWER_STATE_ULPS_EXIT                      (0x1 << 1)
+#define DSI_POWER_STATE_ULPS_OFFSET                    (0x1)
+
+
+#define DSI_ONE_DATA_LANE                                      (0x1)
+#define DSI_TWO_DATA_LANE                                      (0x2)
+#define DSI_THREE_DATA_LANE                                    (0X3)
+#define DSI_FOUR_DATA_LANE                                     (0x4)
+#define DSI_DPI_VIRT_CHANNEL_OFFSET                    (0x3)
+#define DSI_DBI_VIRT_CHANNEL_OFFSET                    (0x5)
+#define DSI_DPI_COLOR_FORMAT_RGB565                    (0x01 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB666                    (0x02 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK     (0x03 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB888                    (0x04 << 7)
+#define DSI_DBI_COLOR_FORMAT_OPTION2           (0x05 << 13)
+
+#define DSI_INTR_STATE_RXSOTERROR                      BIT(0)
+
+#define DSI_INTR_STATE_SPL_PKG_SENT                    BIT(30)
+#define DSI_INTR_STATE_TE                                      BIT(31)
+
+#define DSI_HS_TX_TIMEOUT_MASK                         (0xffffff)
+
+#define DSI_LP_RX_TIMEOUT_MASK                         (0xffffff)
+
+#define DSI_TURN_AROUND_TIMEOUT_MASK           (0x3f)
+
+#define DSI_RESET_TIMER_MASK                           (0xffff)
+
+#define DSI_DBI_FIFO_WM_HALF                           (0x0)
+#define DSI_DBI_FIFO_WM_QUARTER                                (0x1)
+#define DSI_DBI_FIFO_WM_LOW                                    (0x2)
+
+#define DSI_DPI_TIMING_MASK                                    (0xffff)
+
+#define DSI_INIT_TIMER_MASK                                    (0xffff)
+
+#define DSI_DBI_RETURN_PACK_SIZE_MASK          (0x3ff)
+
+#define DSI_LP_BYTECLK_MASK                                    (0x0ffff)
+
+#define DSI_HS_CTRL_GEN_SHORT_W0                       (0x03)
+#define DSI_HS_CTRL_GEN_SHORT_W1                       (0x13)
+#define DSI_HS_CTRL_GEN_SHORT_W2                       (0x23)
+#define DSI_HS_CTRL_GEN_R0                                     (0x04)
+#define DSI_HS_CTRL_GEN_R1                                     (0x14)
+#define DSI_HS_CTRL_GEN_R2                                     (0x24)
+#define DSI_HS_CTRL_GEN_LONG_W                         (0x29)
+#define DSI_HS_CTRL_MCS_SHORT_W0                       (0x05)
+#define DSI_HS_CTRL_MCS_SHORT_W1                       (0x15)
+#define DSI_HS_CTRL_MCS_R0                                     (0x06)
+#define DSI_HS_CTRL_MCS_LONG_W                         (0x39)
+#define DSI_HS_CTRL_VC_OFFSET                          (0x06)
+#define DSI_HS_CTRL_WC_OFFSET                          (0x08)
+
+#define        DSI_FIFO_GEN_HS_DATA_FULL                       BIT(0)
+#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY                BIT(1)
+#define DSI_FIFO_GEN_HS_DATA_EMPTY                     BIT(2)
+#define DSI_FIFO_GEN_LP_DATA_FULL                      BIT(8)
+#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY                BIT(9)
+#define DSI_FIFO_GEN_LP_DATA_EMPTY                     BIT(10)
+#define DSI_FIFO_GEN_HS_CTRL_FULL                      BIT(16)
+#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY                BIT(17)
+#define DSI_FIFO_GEN_HS_CTRL_EMPTY                     BIT(18)
+#define DSI_FIFO_GEN_LP_CTRL_FULL                      BIT(24)
+#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY                BIT(25)
+#define DSI_FIFO_GEN_LP_CTRL_EMPTY                     BIT(26)
+#define DSI_FIFO_DBI_EMPTY                                     BIT(27)
+#define DSI_FIFO_DPI_EMPTY                                     BIT(28)
+
+#define DSI_DBI_HS_LP_SWITCH_MASK                      (0x1)
+
+#define DSI_HS_LP_SWITCH_COUNTER_OFFSET                (0x0)
+#define DSI_LP_HS_SWITCH_COUNTER_OFFSET                (0x16)
+
+#define DSI_DPI_CTRL_HS_SHUTDOWN                       (0x00000001)
+#define DSI_DPI_CTRL_HS_TURN_ON                                (0x00000002)
+
+/*dsi power modes*/
+#define DSI_POWER_MODE_DISPLAY_ON      BIT(2)
+#define DSI_POWER_MODE_NORMAL_ON       BIT(3)
+#define DSI_POWER_MODE_SLEEP_OUT       BIT(4)
+#define DSI_POWER_MODE_PARTIAL_ON      BIT(5)
+#define DSI_POWER_MODE_IDLE_ON         BIT(6)
+
+typedef enum {
+               MDFLD_DSI_ENCODER_DBI = 0,
+               MDFLD_DSI_ENCODER_DPI,
+} mdfld_dsi_encoder_t;
+
+enum {
+       MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
+       MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
+       MDFLD_DSI_VIDEO_BURST_MODE = 3,
+};
+
+#define DSI_DPI_COMPLETE_LAST_LINE                     BIT(2)
+#define DSI_DPI_DISABLE_BTA                                    BIT(3)
+
+struct mdfld_dsi_connector_state {
+       u32 mipi_ctrl_reg;
+};
+
+struct mdfld_dsi_encoder_state {
+
+};
+
+struct mdfld_dsi_connector {
+       /*
+        * This is ugly, but I have to use connector in it! :-(
+        * FIXME: use drm_connector instead.
+        */ 
+       struct psb_intel_output base;
+       
+       int pipe;
+       void * private;
+       void * pkg_sender;
+
+       /*connection status*/
+       enum drm_connector_status status;
+};
+
+struct mdfld_dsi_encoder {
+       struct drm_encoder base;
+       void * private;
+};
+
+/*
+ * DSI config, consists of one DSI connector, two DSI encoders.
+ * DRM will pick up on DSI encoder basing on differents configs.
+ */
+struct mdfld_dsi_config {
+       struct drm_device * dev;
+       struct drm_display_mode * fixed_mode;
+       struct drm_display_mode * mode;
+       
+       struct mdfld_dsi_connector * connector;
+       struct mdfld_dsi_encoder * encoders[DRM_CONNECTOR_MAX_ENCODER];
+       struct mdfld_dsi_encoder * encoder;
+       
+       int changed;
+       
+       int bpp;
+       mdfld_dsi_encoder_t type;
+       int lane_count;
+       /*Virtual channel number for this encoder*/
+       int channel_num;
+       /*video mode configure*/
+       int video_mode;
+
+       int dvr_ic_inited;
+};
+
+#define MDFLD_DSI_CONNECTOR(psb_output) \
+               (container_of(psb_output, struct mdfld_dsi_connector, base))
+               
+#define MDFLD_DSI_ENCODER(encoder) \
+               (container_of(encoder, struct mdfld_dsi_encoder, base))
+               
+static inline struct mdfld_dsi_config * 
+       mdfld_dsi_get_config(struct mdfld_dsi_connector * connector)
+{
+       if(!connector) {
+               return NULL;
+       }
+       
+       return (struct mdfld_dsi_config *)connector->private;
+}
+
+static inline void * mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config * config)
+{
+       struct mdfld_dsi_connector * dsi_connector;
+       
+       if(!config)
+               return NULL;
+               
+       dsi_connector = config->connector;
+       
+       if(!dsi_connector)
+               return NULL;
+       
+       return dsi_connector->pkg_sender;
+}
+
+static inline struct mdfld_dsi_config *
+       mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder * encoder)
+{
+       if(!encoder)
+               return NULL;
+       return (struct mdfld_dsi_config *)encoder->private;
+}
+
+static inline struct mdfld_dsi_connector * 
+       mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder * encoder)
+{
+       struct mdfld_dsi_config * config;
+       
+       if(!encoder)
+               return NULL;
+               
+       config = mdfld_dsi_encoder_get_config(encoder);
+       if(!config)
+               return NULL;
+               
+       return config->connector;
+}
+
+static inline void * mdfld_dsi_encoder_get_pkg_sender(struct mdfld_dsi_encoder * encoder)
+{
+       struct mdfld_dsi_config * dsi_config;
+       
+       dsi_config = mdfld_dsi_encoder_get_config(encoder);
+       if(!dsi_config)
+               return NULL;
+               
+       return mdfld_dsi_get_pkg_sender(dsi_config);
+}
+
+static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder * encoder)
+{
+       struct mdfld_dsi_connector * connector;
+       
+       if(!encoder)
+               return -1;
+               
+       connector = mdfld_dsi_encoder_get_connector(encoder);
+       if(!connector)
+               return -1;
+               
+       return connector->pipe;
+}
+
+/*Export functions*/
+extern void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat);
+extern void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe);
+extern void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level);
+extern void mdfld_dsi_output_init(struct drm_device * dev,
+                               int pipe,
+                               struct mdfld_dsi_config * config,
+                               struct panel_funcs * p_cmd_funcs,
+                               struct panel_funcs * p_vid_funcs);
+extern void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe);
+
+extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
+                               u32 *mode, bool hs);
+extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
+                                       u32 *result, bool hs);
+extern int mdfld_dsi_panel_reset(int pipe);
+
+#endif /*__MDFLD_DSI_OUTPUT_H__*/
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c b/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c
new file mode 100644 (file)
index 0000000..fb4d135
--- /dev/null
@@ -0,0 +1,890 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include <linux/freezer.h>
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+
+#define FLD_MASK(start, end)   (((1 << ((start) - (end) + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
+#define FLD_MOD(orig, val, start, end) \
+       (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
+
+#define MDFLD_DSI_DBI_FIFO_TIMEOUT             100
+#define MDFLD_DSI_READ_MAX_COUNT               5000
+
+enum data_type {
+       DSI_DT_GENERIC_SHORT_WRITE_0    = 0x03,
+       DSI_DT_GENERIC_SHORT_WRITE_1    = 0x13,
+       DSI_DT_GENERIC_SHORT_WRITE_2    = 0x23,
+       DSI_DT_GENERIC_READ_0           = 0x04,
+       DSI_DT_GENERIC_READ_1           = 0x14,
+       DSI_DT_GENERIC_READ_2           = 0x24,
+       DSI_DT_GENERIC_LONG_WRITE       = 0x29,
+       DSI_DT_DCS_SHORT_WRITE_0        = 0x05,
+       DSI_DT_DCS_SHORT_WRITE_1        = 0x15,
+       DSI_DT_DCS_READ                 = 0x06,
+       DSI_DT_DCS_LONG_WRITE           = 0x39,
+};
+
+enum {
+       MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
+};
+
+enum {
+       MDFLD_DSI_PKG_SENDER_FREE = 0x0,
+       MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
+};
+
+static const char * dsi_errors[] = {
+       "RX SOT Error",
+       "RX SOT Sync Error",
+       "RX EOT Sync Error",
+       "RX Escape Mode Entry Error",
+       "RX LP TX Sync Error",
+       "RX HS Receive Timeout Error",
+       "RX False Control Error",
+       "RX ECC Single Bit Error",
+       "RX ECC Multibit Error",
+       "RX Checksum Error",
+       "RX DSI Data Type Not Recognised",
+       "RX DSI VC ID Invalid",
+       "TX False Control Error",
+       "TX ECC Single Bit Error",
+       "TX ECC Multibit Error",
+       "TX Checksum Error",
+       "TX DSI Data Type Not Recognised",
+       "TX DSI VC ID invalid",
+       "High Contention",
+       "Low contention",
+       "DPI FIFO Under run",
+       "HS TX Timeout",
+       "LP RX Timeout",
+       "Turn Around ACK Timeout",
+       "ACK With No Error",
+       "RX Invalid TX Length",
+       "RX Prot Violation",
+       "HS Generic Write FIFO Full",
+       "LP Generic Write FIFO Full",
+       "Generic Read Data Avail"
+       "Special Packet Sent",
+       "Tearing Effect",
+};
+
+static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender * sender,
+                                               u32 mask)
+{
+       struct drm_device * dev = sender->dev;
+       u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
+       int retry = 0xffff;
+       
+       while(retry--) {
+               if((mask & REG_READ(gen_fifo_stat_reg)) == mask)
+                       return 0;
+               udelay(100);
+       }
+       
+       DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg));
+       return -EIO;
+}
+
+static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender * sender)
+{
+       return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) | BIT(26) | BIT(27) | BIT(28)));
+}
+
+static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender * sender)
+{
+       return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26)));
+}
+
+static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender * sender)
+{
+       return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18)));
+}
+
+static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender * sender)
+{
+       return wait_for_gen_fifo_empty(sender, (BIT(27)));
+}
+
+static int handle_dsi_error(struct mdfld_dsi_pkg_sender * sender, u32 mask)
+{
+       u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+       struct drm_device * dev = sender->dev;
+       
+       PSB_DEBUG_ENTRY("Handling error 0x%08x\n", mask);
+       
+       switch(mask) {
+       case BIT(0):
+       case BIT(1):
+       case BIT(2):
+       case BIT(3):
+       case BIT(4):
+       case BIT(5):
+       case BIT(6):
+       case BIT(7):
+       case BIT(8):
+       case BIT(9):
+       case BIT(10):
+       case BIT(11):
+       case BIT(12):
+       case BIT(13):
+               PSB_DEBUG_ENTRY("No Action required\n");
+               break;
+       case BIT(14):
+               /*wait for all fifo empty*/
+               /*wait_for_all_fifos_empty(sender)*/;
+               break;
+       case BIT(15):
+               PSB_DEBUG_ENTRY("No Action required\n");
+               break;
+       case BIT(16):
+               break;
+       case BIT(17):
+               break;
+       case BIT(18):
+       case BIT(19):
+               PSB_DEBUG_ENTRY("High/Low contention detected\n");
+               /*wait for contention recovery time*/
+               /*mdelay(10);*/
+               /*wait for all fifo empty*/
+               if(0) wait_for_all_fifos_empty(sender);
+               break;
+       case BIT(20):
+               PSB_DEBUG_ENTRY("No Action required\n");
+               break;
+       case BIT(21):
+               /*wait for all fifo empty*/
+               /*wait_for_all_fifos_empty(sender);*/
+               break;
+       case BIT(22):
+               break;
+       case BIT(23):
+       case BIT(24):
+       case BIT(25):
+       case BIT(26):
+       case BIT(27):
+               PSB_DEBUG_ENTRY("HS Gen fifo full\n");
+               REG_WRITE(intr_stat_reg, mask);
+               wait_for_hs_fifos_empty(sender);
+               break;
+       case BIT(28):
+               PSB_DEBUG_ENTRY("LP Gen fifo full\n");
+               REG_WRITE(intr_stat_reg, mask);
+               wait_for_lp_fifos_empty(sender);
+               break;
+       case BIT(29):
+       case BIT(30):
+       case BIT(31):
+               PSB_DEBUG_ENTRY("No Action required\n");
+               break;
+       }
+       
+       if(mask & REG_READ(intr_stat_reg)) {
+               PSB_DEBUG_ENTRY("Cannot clean interrupt 0x%08x\n", mask);
+       }
+       
+       return 0;
+}
+
+static int dsi_error_handler(struct mdfld_dsi_pkg_sender * sender)
+{
+       struct drm_device * dev = sender->dev;
+       u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+       u32 mask;
+       u32 intr_stat;
+       int i;
+       int err = 0;
+
+       intr_stat = REG_READ(intr_stat_reg);
+               
+       for(i=0; i<32; i++) {
+               mask = (0x00000001UL) << i;
+               if(intr_stat & mask) {
+                       PSB_DEBUG_ENTRY("[DSI]: %s\n", dsi_errors[i]);
+                       err = handle_dsi_error(sender, mask);
+                       if(err)
+                               DRM_ERROR("Cannot handle error\n");
+               }
+       }
+       
+       return err;
+}
+
+static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender * sender)
+{
+       struct drm_device * dev = sender->dev;
+       u32 retry = 0xffff;
+       u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
+       int ret = 0;
+
+        /*query the command execution status*/
+        while(retry--) {
+                if(!(REG_READ(dbi_cmd_addr_reg) & BIT(0)))
+                        break;
+        }
+
+        if(!retry) {
+                DRM_ERROR("Timeout waiting for DBI Command status\n");
+                ret = -EAGAIN;
+        }
+
+       return ret;
+}
+
+static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 cmd, u8 param, bool hs)
+{
+       struct drm_device * dev = sender->dev;
+       u32 ctrl_reg;
+       u32 val;
+       u8 virtual_channel = 0;
+
+       if (hs) {
+               ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+
+               /* FIXME: wait_for_hs_fifos_empty(sender); */
+       } else {
+               ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+
+               /* FIXME: wait_for_lp_fifos_empty(sender); */
+       }
+
+       val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) |
+               FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0);
+
+       REG_WRITE(ctrl_reg, val);
+
+       return 0;
+}
+
+static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 *data, int len, bool hs)
+{
+       struct drm_device * dev = sender->dev;
+       u32 ctrl_reg;
+       u32 data_reg;
+       u32 val;
+       u8 *p;
+       u8 b1, b2, b3, b4;
+       u8 virtual_channel = 0;
+       int i;
+
+       if (hs) {
+               ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+               data_reg = sender->mipi_hs_gen_data_reg;
+
+               /* FIXME: wait_for_hs_fifos_empty(sender); */
+       } else {
+               ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+               data_reg = sender->mipi_lp_gen_data_reg;
+
+               /* FIXME: wait_for_lp_fifos_empty(sender); */
+       }
+
+       p = data;
+       for (i = 0; i < len / 4; i++) {
+               b1 = *p++;
+               b2 = *p++;
+               b3 = *p++;
+               b4 = *p++;
+
+               REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1);
+       }
+
+       i = len % 4;
+       if (i) {
+               b1 = 0; b2 = 0; b3 = 0;
+
+               switch (i) {
+               case 3:
+                       b1 = *p++;
+                       b2 = *p++;
+                       b3 = *p++;
+                       break;
+               case 2:
+                       b1 = *p++;
+                       b2 = *p++;
+                       break;
+               case 1:
+                       b1 = *p++;
+                       break;
+               }
+
+               REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1);
+       }
+
+       val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) |
+               FLD_VAL(data_type, 5, 0);
+
+       REG_WRITE(ctrl_reg, val);
+
+       return 0;
+}
+
+static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 *data, u16 len)
+{
+       u8 cmd;
+       
+       PSB_DEBUG_ENTRY("Prepare to Send type 0x%x pkg\n", data_type);
+       
+       switch (data_type) {
+       case DSI_DT_DCS_SHORT_WRITE_0:
+       case DSI_DT_DCS_SHORT_WRITE_1:
+       case DSI_DT_DCS_LONG_WRITE:
+               cmd = *data;
+               break;
+       default:
+               return 0;
+       }
+       
+       /*this prevents other package sending while doing msleep*/
+       sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
+       
+       /*wait for 120 milliseconds in case exit_sleep_mode just be sent*/
+       if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
+               /*TODO: replace it with msleep later*/
+               mdelay(120);
+       }
+
+       if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
+               /*TODO: replace it with msleep later*/
+               mdelay(120);
+       }
+       
+       return 0;
+}
+
+static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 *data, u16 len)
+{
+       u8 cmd;
+       
+       PSB_DEBUG_ENTRY("Sent type 0x%x pkg\n", data_type);
+       
+       switch (data_type) {
+       case DSI_DT_DCS_SHORT_WRITE_0:
+       case DSI_DT_DCS_SHORT_WRITE_1:
+       case DSI_DT_DCS_LONG_WRITE:
+               cmd = *data;
+               break;
+       default:
+               return 0;
+       }
+       
+       /*update panel status*/
+       if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
+               sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
+               /*TODO: replace it with msleep later*/
+               mdelay(120);
+       } else if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
+               sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
+               /*TODO: replace it with msleep later*/
+               mdelay(120);
+       } else if (unlikely(cmd == DCS_SOFT_RESET)) {
+               /*TODO: replace it with msleep later*/
+               mdelay(5);
+       }
+       
+       sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+       
+       return 0;
+       
+}
+
+static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+               u8 *data, u16 len, bool hs)
+{
+       int ret;
+       
+       /*handle DSI error*/
+       ret = dsi_error_handler(sender);
+       if (ret) {
+               DRM_ERROR("Error handling failed\n");
+               return -EAGAIN;
+       }
+
+       /* send pkg */
+       PSB_DEBUG_ENTRY("Sending type 0x%x pkg\n", data_type);
+       
+       if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
+               DRM_ERROR("sender is busy\n");
+               return -EAGAIN;
+       }
+       
+       ret = send_pkg_prepare(sender, data_type, data, len);
+       if (ret) {
+               DRM_ERROR("send_pkg_prepare error\n");
+               return ret;
+       }
+       
+       switch (data_type) {
+       case DSI_DT_GENERIC_SHORT_WRITE_0:
+       case DSI_DT_GENERIC_SHORT_WRITE_1:
+       case DSI_DT_GENERIC_SHORT_WRITE_2:
+       case DSI_DT_GENERIC_READ_0:
+       case DSI_DT_GENERIC_READ_1:
+       case DSI_DT_GENERIC_READ_2:
+       case DSI_DT_DCS_SHORT_WRITE_0:
+       case DSI_DT_DCS_SHORT_WRITE_1:
+       case DSI_DT_DCS_READ:
+               ret = send_short_pkg(sender, data_type, data[0], data[1], hs);
+               break;
+       case DSI_DT_GENERIC_LONG_WRITE:
+       case DSI_DT_DCS_LONG_WRITE:
+               ret = send_long_pkg(sender, data_type, data, len, hs);
+               break;
+       }
+
+       send_pkg_done(sender, data_type, data, len);
+
+       /*FIXME: should I query complete and fifo empty here?*/
+
+       return ret;
+}
+
+static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender * sender, struct psb_gtt * pg, int pipe) {
+       uint32_t phy;
+       void __iomem *virt_addr = NULL;
+
+       switch(pipe) {
+       case 0:
+               phy = pg->gtt_phys_start - 0x1000;
+               break;
+       case 2:
+               phy = pg->gtt_phys_start - 0x800;
+               break;
+       default:
+               DRM_ERROR("Unsupported channel\n");
+               return -EINVAL;
+       }
+
+       /*mapping*/
+       virt_addr = ioremap_nocache(phy, 0x800);
+       if(!virt_addr) {
+               DRM_ERROR("Map DBI command buffer error\n");
+               return -ENOMEM;
+       }
+
+       sender->dbi_cb_phy = phy;
+       sender->dbi_cb_addr = virt_addr;
+
+       PSB_DEBUG_ENTRY("DBI command buffer initailized. phy %x, addr %p\n", phy, virt_addr);
+
+       return 0;
+}
+
+static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender * sender) {
+       PSB_DEBUG_ENTRY("\n");
+       
+       if(sender && sender->dbi_cb_addr)
+               iounmap(sender->dbi_cb_addr);
+}
+
+int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+                       u32 len, bool hs)
+{
+       unsigned long flags;
+       
+       if (!sender || !data || !len) {
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&sender->lock, flags);
+       send_pkg(sender, DSI_DT_DCS_LONG_WRITE, data, len, hs);
+       spin_unlock_irqrestore(&sender->lock, flags);
+       
+       return 0;
+}
+
+int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+                       u8 param, u8 param_num, bool hs)
+{
+       u8 data[2];
+       unsigned long flags;
+       u8 data_type;
+
+       if (!sender) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       data[0] = cmd;
+
+       if (param_num) {
+               data_type = DSI_DT_DCS_SHORT_WRITE_1;
+               data[1] = param;
+       } else {
+               data_type = DSI_DT_DCS_SHORT_WRITE_0;
+               data[1] = 0;
+       }
+       
+       spin_lock_irqsave(&sender->lock, flags);
+       send_pkg(sender, data_type, data, sizeof(data), hs);
+       spin_unlock_irqrestore(&sender->lock, flags);
+       
+       return 0;
+}
+
+int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
+                       u8 param1, u8 param_num, bool hs)
+{
+       u8 data[2];
+       unsigned long flags;
+       u8 data_type;
+
+       if (!sender || param_num < 0 || param_num > 2) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       switch (param_num) {
+       case 0:
+               data_type = DSI_DT_GENERIC_SHORT_WRITE_0;
+               data[0] = 0;
+               data[1] = 0;
+               break;
+       case 1:
+               data_type = DSI_DT_GENERIC_SHORT_WRITE_1;
+               data[0] = param0;
+               data[1] = 0;
+               break;
+       case 2:
+               data_type = DSI_DT_GENERIC_SHORT_WRITE_2;
+               data[0] = param0;
+               data[1] = param1;
+               break;
+       }
+
+       spin_lock_irqsave(&sender->lock, flags);
+       send_pkg(sender, data_type, data, sizeof(data), hs);
+       spin_unlock_irqrestore(&sender->lock, flags);
+
+       return 0;       
+}
+
+int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+                       u32 len, bool hs)
+{
+       unsigned long flags;
+
+       if (!sender || !data || !len) {
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&sender->lock, flags);
+       send_pkg(sender, DSI_DT_GENERIC_LONG_WRITE, data, len, hs);
+       spin_unlock_irqrestore(&sender->lock, flags);
+       
+       return 0;
+}
+
+static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
+{
+       unsigned long flags;
+       struct drm_device *dev = sender->dev;
+       int i;
+       u32 gen_data_reg;
+       int retry = MDFLD_DSI_READ_MAX_COUNT;
+
+       if (!sender || !data_out || !len_out) {
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       /**
+        * do reading.
+        * 0) send out generic read request
+        * 1) polling read data avail interrupt
+        * 2) read data
+        */
+       spin_lock_irqsave(&sender->lock, flags);
+
+       REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
+
+       if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29)))
+               DRM_ERROR("Can NOT clean read data valid interrupt\n");
+
+       /*send out read request*/
+       send_pkg(sender, data_type, data, len, hs);
+
+       /*polling read data avail interrupt*/
+       while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) {
+               udelay(100);
+               retry--;
+       }
+
+       if (!retry) {
+               spin_unlock_irqrestore(&sender->lock, flags);
+               return -ETIMEDOUT;
+       }
+
+       REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
+
+       /*read data*/
+       if (hs)
+               gen_data_reg = sender->mipi_hs_gen_data_reg;
+       else
+               gen_data_reg = sender->mipi_lp_gen_data_reg;
+
+       for (i = 0; i < len_out; i++)
+               *(data_out + i) = REG_READ(gen_data_reg);
+
+       spin_unlock_irqrestore(&sender->lock, flags);
+
+       return 0;
+}
+
+static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender, u8 param0,
+                       u8 param1, u8 param_num, u32 *data, u16 len, bool hs)
+{
+       u8 data_type;
+       u8 cmd[2];
+
+       switch (param_num) {
+       case 0:
+               data_type = DSI_DT_GENERIC_READ_0;
+               cmd[0] = 0;
+               cmd[1] = 0;
+               break;
+       case 1:
+               data_type = DSI_DT_GENERIC_READ_1;
+               cmd[0] = param0;
+               cmd[1] = 0;
+               break;
+       case 2:
+               data_type = DSI_DT_GENERIC_READ_2;
+               cmd[0] = param0;
+               cmd[1] = param1;
+               break;
+       default:
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       return __read_panel_data(sender, data_type, cmd, sizeof(cmd),
+                               data, len, hs);
+}
+
+int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+               u32 *data, u16 len, bool hs)
+{
+       if (!sender || !data || !len) {
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       return __read_panel_data(sender, DSI_DT_DCS_READ, &cmd, 1,
+                               data, len, hs);
+}
+
+int mdfld_dsi_write_mem_start(struct mdfld_dsi_pkg_sender *sender)
+{
+       struct drm_device *dev = sender->dev;
+       u32 index = 0;
+       u8 *cb = (u8 *)sender->dbi_cb_addr;
+       int retry;
+       
+       if (!sender) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+       
+       if (!sender->dbi_pkg_support) {
+               DRM_ERROR("No DBI pkg sending on this sender\n");
+               return -ENOTSUPP;
+       }
+
+       if (!spin_trylock(&sender->lock))
+               return -EAGAIN;
+
+       /**
+        * query whether DBI FIFO is empty,
+        * if not wait it becoming empty
+        */
+       retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
+       while (retry && !(REG_READ(sender->mipi_gen_fifo_stat_reg) & BIT(27))) {
+               udelay(500);
+               retry--;
+       }
+
+       /*if DBI FIFO timeout, drop this frame*/
+       if (!retry) {
+               spin_unlock(&sender->lock);
+               return 0;
+       }
+
+       *(cb + (index++)) = write_mem_start;
+
+       REG_WRITE(sender->mipi_cmd_len_reg, 1);
+       REG_WRITE(sender->mipi_cmd_addr_reg, sender->dbi_cb_phy | BIT(0) | BIT(1));
+
+       retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
+       while (retry && (REG_READ(sender->mipi_cmd_addr_reg) & BIT(0))) {
+               udelay(1);
+               retry--;
+       }
+
+       spin_unlock(&sender->lock);
+
+       return 0;
+}
+
+int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector * dsi_connector, int pipe)
+{
+       int ret;
+       struct mdfld_dsi_pkg_sender * pkg_sender;
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+       struct drm_device * dev = dsi_config->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct psb_gtt * pg = dev_priv->pg;
+       u32 mipi_val = 0;
+       
+       PSB_DEBUG_ENTRY("\n");
+       
+       if(!dsi_connector) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+       
+       pkg_sender = dsi_connector->pkg_sender;
+       
+       if(!pkg_sender || IS_ERR(pkg_sender)) {
+               pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender), GFP_KERNEL);
+               if(!pkg_sender) {
+                       DRM_ERROR("Create DSI pkg sender failed\n");
+                       return -ENOMEM;
+               }
+               
+               dsi_connector->pkg_sender = (void *)pkg_sender;
+       }
+
+       pkg_sender->dev = dev;
+       pkg_sender->dsi_connector = dsi_connector;
+       pkg_sender->pipe = pipe;
+       pkg_sender->pkg_num = 0;
+       pkg_sender->panel_mode = 0;
+       pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+       
+       /*int dbi command buffer*/
+       if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+               pkg_sender->dbi_pkg_support = 1;
+               ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe);
+               if(ret) {
+                       DRM_ERROR("DBI command buffer map failed\n");
+                       goto mapping_err;
+               }
+       }
+       
+       /*init regs*/
+       if(pipe == 0) {
+               pkg_sender->dpll_reg = MRST_DPLL_A;
+               pkg_sender->dspcntr_reg = DSPACNTR;
+               pkg_sender->pipeconf_reg = PIPEACONF;
+               pkg_sender->dsplinoff_reg = DSPALINOFF;
+               pkg_sender->dspsurf_reg = DSPASURF;
+               pkg_sender->pipestat_reg = PIPEASTAT;
+       } else if (pipe == 2) {
+               pkg_sender->dpll_reg = MRST_DPLL_A;
+               pkg_sender->dspcntr_reg = DSPCCNTR;
+               pkg_sender->pipeconf_reg = PIPECCONF;
+               pkg_sender->dsplinoff_reg = DSPCLINOFF;
+               pkg_sender->dspsurf_reg = DSPCSURF;
+               pkg_sender->pipestat_reg = PIPECSTAT;
+       }
+
+       pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
+       pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
+       pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
+       pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
+       pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
+       pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+       pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
+       pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
+       pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
+       pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);
+
+       /*init lock*/
+       spin_lock_init(&pkg_sender->lock);
+
+       if (get_panel_type(dev, pipe) != TC35876X) {
+               /**
+                * For video mode, don't enable DPI timing output here,
+                * will init the DPI timing output during mode setting.
+                */
+               if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+                       mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+               else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+                       mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX
+                               | TE_TRIGGER_GPIO_PIN;
+               else
+                       DRM_ERROR("Bad DSI encoder type\n");
+
+               if (pipe == 0)
+                       mipi_val |= 0x2;
+
+               REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
+               REG_READ(MIPI_PORT_CONTROL(pipe));
+
+               /* do dsi controller init */
+               mdfld_dsi_controller_init(dsi_config, pipe);
+       }
+
+       PSB_DEBUG_ENTRY("initialized\n");
+       
+       return 0;
+
+mapping_err:
+       kfree(pkg_sender);
+       dsi_connector->pkg_sender = NULL;
+       
+       return ret;
+}
+
+void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender * sender)
+{
+       if(!sender || IS_ERR(sender))
+               return;
+
+       /*free mapped command buffer*/
+       mdfld_dbi_cb_destroy(sender);
+       
+       /*free*/
+       kfree(sender);
+       
+       PSB_DEBUG_ENTRY("destroyed\n");
+}
+
+
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.h b/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.h
new file mode 100644 (file)
index 0000000..91b9675
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+#ifndef __MDFLD_DSI_PKG_SENDER_H__
+#define __MDFLD_DSI_PKG_SENDER_H__
+
+#include <linux/kthread.h>
+
+#define MDFLD_MAX_DCS_PARAM    8
+
+struct mdfld_dsi_pkg_sender {
+       struct drm_device * dev;
+       struct mdfld_dsi_connector * dsi_connector;
+       u32 status;
+       
+       u32 panel_mode;
+               
+       int pipe;
+       
+       spinlock_t lock;
+       
+       u32 pkg_num;
+       
+       int dbi_pkg_support;
+       
+       u32 dbi_cb_phy;
+       void __iomem *dbi_cb_addr;
+       
+       /*registers*/
+       u32 dpll_reg;
+       u32 dspcntr_reg;
+       u32 pipeconf_reg;
+       u32 pipestat_reg;
+       u32 dsplinoff_reg;
+       u32 dspsurf_reg;
+       
+       u32 mipi_intr_stat_reg;
+       u32 mipi_lp_gen_data_reg;
+       u32 mipi_hs_gen_data_reg;
+       u32 mipi_lp_gen_ctrl_reg;
+       u32 mipi_hs_gen_ctrl_reg;
+       u32 mipi_gen_fifo_stat_reg;
+       u32 mipi_data_addr_reg;
+       u32 mipi_data_len_reg;
+       u32 mipi_cmd_addr_reg;
+       u32 mipi_cmd_len_reg;
+};
+
+/*DCS definitions*/
+#define DCS_SOFT_RESET                 0x01
+#define DCS_ENTER_SLEEP_MODE           0x10
+#define DCS_EXIT_SLEEP_MODE            0x11
+#define DCS_SET_DISPLAY_OFF            0x28
+#define DCS_SET_DISPLAY_ON             0x29
+#define DCS_SET_COLUMN_ADDRESS         0x2a
+#define DCS_SET_PAGE_ADDRESS           0x2b
+#define DCS_WRITE_MEM_START            0x2c
+#define DCS_SET_TEAR_OFF               0x34
+#define DCS_SET_TEAR_ON                0x35
+
+extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector * dsi_connector, int pipe);
+extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender * sender);
+int mdfld_dsi_write_mem_start(struct mdfld_dsi_pkg_sender *sender);
+int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+                       u8 param, u8 param_num, bool hs);
+int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+                       u32 len, bool hs);
+int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
+                       u8 param1, u8 param_num, bool hs);
+int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+                       u32 len, bool hs);
+
+/*read interfaces*/
+int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+               u32 *data, u16 len, bool hs);
+
+#endif
diff --git a/drivers/staging/mrst/drv/mdfld_gl3.c b/drivers/staging/mrst/drv/mdfld_gl3.c
new file mode 100644 (file)
index 0000000..0b58f46
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Jim Bish <jim.bish@@intel.com>
+ */
+
+#ifdef CONFIG_MDFD_GL3
+
+#include "mdfld_gl3.h"
+#include "psb_powermgmt.h"
+
+void gl3_enable(void)
+{
+       struct drm_psb_private *dev_priv =
+                   (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+       PSB_DEBUG_ENTRY("gl3_enable called on platform %x\n",   dev_priv->platform_rev_id);
+       if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+               return;
+       MDFLD_GL3_WRITE(MDFLD_GL3_ENABLE_CACHE, MDFLD_GL3_CONTROL);
+       PSB_DEBUG_GENERAL("gl3 cache enabled with mask %x\n",
+                       MDFLD_GL3_ENABLE_CACHE);
+       ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+void gl3_disable(void)
+{
+       struct drm_psb_private *dev_priv =
+                   (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+       PSB_DEBUG_ENTRY("gl3_disable called on platform %x\n",  dev_priv->platform_rev_id);
+       if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+               return;
+       MDFLD_GL3_WRITE(MDFLD_GL3_DISABLE_CACHE, MDFLD_GL3_CONTROL);
+       PSB_DEBUG_GENERAL("gl3 cache disabled with mask %x\n",
+                       MDFLD_GL3_DISABLE_CACHE);
+       ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+void gl3_invalidate(void)
+{
+       struct drm_psb_private *dev_priv =
+                   (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+       PSB_DEBUG_ENTRY("gl3_invalidate called on platform %x\n",       dev_priv->platform_rev_id);
+       if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+               return;
+       // Invalidate the cache
+       MDFLD_GL3_WRITE(MDFLD_GL3_INVALIDATE_CACHE, MDFLD_GL3_CONTROL);
+       PSB_DEBUG_GENERAL("gl3 cache invalidated with mask %x\n",
+                       MDFLD_GL3_INVALIDATE_CACHE);
+       ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+void gl3_flush(void)
+{
+       struct drm_psb_private *dev_priv =
+                   (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+       PSB_DEBUG_ENTRY("gl3_flush called on platform %x\n",    dev_priv->platform_rev_id);
+       if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+               return;
+       // Flush the cache
+       MDFLD_GL3_WRITE(MDFLD_GL3_FLUSH_CACHE, MDFLD_GL3_CONTROL);
+       PSB_DEBUG_GENERAL("gl3 cache flushed with mask %x\n",
+                       MDFLD_GL3_FLUSH_CACHE);
+       ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+void gl3_reset(void)
+{
+       struct drm_psb_private *dev_priv =
+                   (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+       PSB_DEBUG_ENTRY("gl3_reset called on platform %x\n",    dev_priv->platform_rev_id);
+       if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+               return;
+       // Reset the cache
+       MDFLD_GL3_WRITE(MDFLD_GL3_SOFT_RESET_ENABLE, MDFLD_GL3_G_CONTROL);
+       PSB_DEBUG_GENERAL("gl3 cache soft reset with mas %x\n",
+                       MDFLD_GL3_SOFT_RESET_ENABLE);
+       ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+#endif /* CONFIG_MDFD_GL3 */
diff --git a/drivers/staging/mrst/drv/mdfld_gl3.h b/drivers/staging/mrst/drv/mdfld_gl3.h
new file mode 100644 (file)
index 0000000..de9a67b
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Jim Bish <jim.bish@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_fb.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include <drm/drm_pciids.h>
+#include "pvr_drm_shared.h"
+#include "psb_powermgmt.h"
+#include <linux/cpu.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+
+#ifdef CONFIG_MDFD_GL3
+
+/*
+ * GL3 Control
+ */
+
+#define MDFLD_GCL_CR_CTL2                              0xB0000
+#define MDFLD_GCL_ERR_ADDR                             0xB0004         /* address at location is the address that had the error */
+#define MDFLD_GCL_ERR_STATUS                   0xB0008
+
+#define MDFLD_IMG_MASK                                 0x20A8          /* unmask bit 21 to get GL3 interrupts */
+/*
+ * GL3 registers and bits
+ */
+
+#define MDFLD_GL3_CONTROL                              0x2100
+#define MDFLD_GL3_USE_WRT_INVAL                        0x2104
+#define MDFLD_GL3_STATUS                               0x2108
+#define MDFLD_GL3_G_CONTROL                            0x20FC
+#define MDFLD_GL3_SOFT_RESET_ENABLE            (1<<4)
+
+#define MDFLD_GL3_DISABLE                              (1<<31)
+#define MDFLD_GL3_BYP_PREQ2_USSE3              (1<<29)
+#define MDLFD_GL3_BYP_PREQ2_USSE2              (1<<28)
+#define MDFLD_GL3_BYP_PREQ2_PDS                        (1<<27)
+#define MDFLD_GL3_BYP_PREQ2_USEC               (1<<26)
+#define MDFLD_GL3_FLUSH                                        (1<<25)
+#define MDFLD_GL3_FLUSH_CTL                            (1<<24)
+#define MDFLD_GL3_BYP_CPU_COH                  (1<<23)
+#define MDFLD_GL3_BYP_VED                              (1<<21)
+#define MDFLD_GL3_BYP_VEC                              (1<<20)
+#define MDFLD_GL3_BYP_GFX                              (1<<19)
+#define MDFLD_GL3_BYP_PREQ1_USE1               (1<<18)
+#define MDFLD_GL3_BYP_PREQ1_USE0               (1<<17)
+#define MDFLD_GL3_BYP_PREQ1_ISPZ               (1<<16)
+#define MDFLD_GL3_BYP_PREQ1_ISPP               (1<<15)
+#define MDFLD_GL3_BYP_PREQ1_TSPP               (1<<14)
+#define MDFLD_GL3_BYP_PREQ1_PBE                        (1<<13)
+#define MDFLD_GL3_BYP_PREQ1_VDM                        (1<<12)
+#define MDFLD_GL3_BYP_PREQ1_TA                 (1<<11)
+#define MDFLD_GL3_BYP_PREQ1_MADD               (1<<10)
+#define MDFLD_GL3_BYP_PREQ1_MMU                        (1<<9)
+#define MDFLD_GL3_USE_INVAL_REQ_USSE3  (1<<8)
+#define MDFLD_GL3_USE_INVAL_REQ_USSE2  (1<<7)
+#define MDFLD_GL3_USE_INVAL_REQ_USSE1  (1<<6)
+#define MDFLD_GL3_USE_INVAL_REQ_USSE0  (1<<5)
+#define MDFLD_GL3_BYP_WR                               (1<<4)
+#define MDFLD_GL3_IGN_VED_HINT                 (1<<3)
+#define MDFLD_GL3_IGN_VEC_HINT                 (1<<2)
+#define MDFLD_GL3_INVALIDATE                   (1<<1)
+#define MDFLD_GL3_PAUSE                                        (1)
+
+/*
+ * GL3 Masks
+ */
+
+#define MDFLD_GL3_ENABLE_CACHE (MDFLD_GL3_BYP_PREQ2_USSE3 | MDLFD_GL3_BYP_PREQ2_USSE2 | \
+                MDFLD_GL3_BYP_PREQ1_USE1 | MDFLD_GL3_BYP_PREQ1_USE0 | \
+                MDFLD_GL3_BYP_VED | MDFLD_GL3_BYP_VEC | \
+                MDFLD_GL3_BYP_PREQ1_ISPZ | MDFLD_GL3_BYP_PREQ1_PBE | MDFLD_GL3_BYP_PREQ1_VDM | \
+                MDFLD_GL3_BYP_PREQ1_TA | MDFLD_GL3_BYP_PREQ1_MMU | MDFLD_GL3_USE_INVAL_REQ_USSE3 | \
+                MDFLD_GL3_USE_INVAL_REQ_USSE2 | MDFLD_GL3_USE_INVAL_REQ_USSE1 | MDFLD_GL3_USE_INVAL_REQ_USSE0 | \
+                MDFLD_GL3_IGN_VEC_HINT)
+
+#define MDFLD_GL3_INVALIDATE_CACHE (MDFLD_GL3_ENABLE_CACHE | MDFLD_GL3_INVALIDATE)
+
+#define MDFLD_GL3_FLUSH_CACHE (MDFLD_GL3_ENABLE_CACHE | MDFLD_GL3_FLUSH)
+
+#define MDFLD_GL3_DISABLE_CACHE (MDFLD_GL3_ENABLE_CACHE | MDFLD_GL3_DISABLE)
+
+// GL3
+#define MDFLD_GL3_WRITE(_val, _offs ) \
+       iowrite32(_val, dev_priv->gl3_reg + (_offs))
+#define MDFLD_GL3_READ(_offs) \
+       ioread32(dev_priv->gl3_reg + (_offs))
+
+void gl3_enable(void);
+void gl3_invalidate(void);
+void gl3_flush(void);
+void gl3_reset(void);
+void gl3_disable(void);
+
+#endif
diff --git a/drivers/staging/mrst/drv/mdfld_hdcp.h b/drivers/staging/mrst/drv/mdfld_hdcp.h
new file mode 100644 (file)
index 0000000..8f4d549
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *     jim liu <jim.liu@intel.com>
+ */
+
+
+#ifndef MDFLD_HDCP_H
+#define MDFLD_HDCP_H
+
+#define MAX_HDCP_DEVICES 127
+#define KSV_SIZE           5
+#define V_SIZE            20
+
+#define HDCP_MAX_RETRY_STATUS 1500
+
+#define HDCP_100MS_DELAY 100 //
+
+typedef struct _hdcp_priv_data {
+    int                        enabled;
+    int                        drmFD;
+    int                        output_id;
+} hdcp_priv_data_t;
+
+typedef struct _sqword {
+       union {
+               unsigned long long quad_part;//ULONGLONG QuadPart;
+               struct {
+                       unsigned long low_part;
+                       unsigned long high_part;
+               } u;
+               struct {
+                       uint8_t byte[8];
+               };
+       };
+} sqword_t;
+
+// A quadword size member 
+//
+typedef struct _hqword {
+       union {
+               struct {
+                       uint64_t major_part: 40;        // lower 40 bits
+                       uint64_t unused1:       24;
+               };
+               struct {
+                       unsigned major_part_low:                32;     // lower 32 bits
+                       unsigned major_part_high:       8;      // lower  bits
+                       unsigned unused2:                       24;
+               };
+               struct {
+                       uint8_t byte[8];
+               };
+       };
+} hqword_t;
+
+// HDCP related definitions are kept here for common usability between 
+// Integrated and External SDVO based HDCP operations
+//I2C Address for HDCP cummnication with Receiver
+#define RX_ADDRESS      0x74000000  // HDCP Port I2C Address (Single Link)
+                                    //  shifted for call back function
+
+//I2C Subaddress Defines - As per the HDCP Spec
+// Downstream spec does not specify which is MSB and LSB?
+#define RX_BKSV_0       0x00    // BKSV[7:0]  
+#define RX_BKSV_1       0x01    // BKSV[15:8]
+#define RX_BKSV_2       0x02    // BKSV[23:16]
+#define RX_BKSV_3       0x03    // BKSV[31:24]
+#define RX_BKSV_4       0x04    // BKSV[39:32]
+#define RX_RI_HIGH      0x08    // Ri'[7:0]
+#define RX_RI_LOW       0x09    // Ri'[15:8]
+#define RX_AKSV_0       0x10    // AKSV[7:0]
+#define RX_AKSV_1       0x11    // AKSV[15:8]
+#define RX_AKSV_2       0x12    // AKSV[23:16]
+#define RX_AKSV_3       0x13    // AKSV[31:24]
+#define RX_AKSV_4       0x14    // AKSV[39:32]... write this byte last
+#define RX_AINFO        0x15    // Receiver register to inform it to enable 1.1 features
+#define RX_AN_0         0x18    // An[7:0]
+#define RX_AN_1         0x19    // An[15:8]
+#define RX_AN_2         0x1A    // An[23:16]
+#define RX_AN_3         0x1B    // An[31:24]
+#define RX_AN_4         0x1C    // An[39:32]
+#define RX_AN_5         0x1D    // An[47:40]
+#define RX_AN_6         0x1E    // An[55:48]
+#define RX_AN_7         0x1F    // An[63:56]
+#define RX_VPRIME_H0_0  0x20    // V'[7:0]
+#define RX_VPRIME_H0_1  0x21    // V'[15:8]
+#define RX_VPRIME_H0_2  0x22    // V'[23:16]
+#define RX_VPRIME_H0_3  0x23    // V'[31:24]
+#define RX_VPRIME_H1_0  0x24    // V'[39:32]
+#define RX_VPRIME_H1_1  0x25    // V'[47:40]
+#define RX_VPRIME_H1_2  0x26    // V'[55:48]
+#define RX_VPRIME_H1_3  0x27    // V'[63:56]
+#define RX_VPRIME_H2_0  0x28    // V'[71:64]
+#define RX_VPRIME_H2_1  0x29    // V'[79:72]
+#define RX_VPRIME_H2_2  0x2A    // V'[87:80]
+#define RX_VPRIME_H2_3  0x2B    // V'[95:88]
+#define RX_VPRIME_H3_0  0x2C    // V'[103:96]
+#define RX_VPRIME_H3_1  0x2D    // V'[111:104]
+#define RX_VPRIME_H3_2  0x2E    // V'[119:112]
+#define RX_VPRIME_H3_3  0x2F    // V'[127:120]
+#define RX_VPRIME_H4_0  0x30    // V'[135:128]
+#define RX_VPRIME_H4_1  0x31    // V'[143:136]
+#define RX_VPRIME_H4_2  0x32    // V'[151:144]
+#define RX_VPRIME_H4_3  0x33    // V'[159:152]
+#define RX_BCAPS        0x40    // [7] RSVD, [6] Repeater, [5] Ready, [4] Fast, [3:2] RSVD, [1] Features, [0] Fast_reauthentication
+#define RX_BSTATUS_0    0x41    // [7] MAX_DEVS_EXCEEDED, [6:0] DEVICE_COUNT
+#define RX_BSTATUS_1    0x42    // [15:14] RSVD, [13] HDMI_RSVD, [12] HDMI_MODE, [11] MAX_CASCADE_EXCEEDED, [10:8] DEPTH
+#define RX_KSV_FIFO     0x43
+
+typedef enum _mdfld_hdcp_rx_data_type_enum {
+    RX_TYPE_BKSV_DATA = 0,
+    RX_TYPE_BCAPS = 1,
+    RX_TYPE_BSTATUS = 2,
+    RX_TYPE_REPEATER_KSV_LIST = 3,
+    RX_TYPE_REPEATER_PRIME_V = 4,
+    RX_TYPE_RI_DATA = 5,
+    RX_TYPE_BINFO  = 6
+} mdfld_hdcp_rx_data_type_en;
+
+typedef struct _hdcp_bstatus {
+       unsigned device_count        : 7;       // [6:0] Total Number of Receiver Devices (excluding repeaters) attached
+       unsigned max_devices_exceeded : 1;      // [7] Topology Error. Greater than 127 devices attached
+       unsigned repeater_depth      : 3;       // [10:8] Repeater depth 
+       unsigned max_cascade_exceeded : 1;      // [11] Topology Error. Greater than 7 levels of Repeater attached
+       unsigned reserved            : 20;      // [31:12] Reserved for future expansion
+} hdcp_bstatus_t;
+
+//
+// BCAPS
+//
+typedef union _hdcp_rx_bcaps
+{
+    uint8_t value;
+    struct {
+        uint8_t fast_reauthantication : 1; // bit 0
+        uint8_t b1_1features_supported : 1; // bit 1
+        uint8_t reserved            : 2; // bi 3:2
+        uint8_t fast_transfer         : 1; // bit 4 ( TRUE  = transfer speed at 400 kHz FALSE = transfer speed at 100 Khz)
+        uint8_t ksv_fifo_ready         : 1; // bit 5
+        uint8_t is_reapeater          : 1; // bit 6
+        uint8_t reserved1           : 1; // bit 7
+    };
+}hdcp_rx_bcaps_t;
+
+//
+// BSTATUS
+//
+typedef union _hdcp_rx_bstatus
+{
+    uint16_t value;
+    struct {
+        uint16_t device_count        : 7; // bit 6:0
+        uint16_t max_devs_exceeded     : 1; // bit 7
+        uint16_t depth              : 3; // bit 10:8
+        uint16_t max_cascade_exceeded  : 1; // bit 11
+        uint16_t rx_in_hdmi_mode        : 1; // bit 12
+        uint16_t rserved            : 3; // bit 15:13
+    };
+}hdcp_rx_bstatus_t;
+
+// HDCP authentication step
+typedef enum _hdcp_authentication_step {
+    HDCP_AUTHENTICATION_STEP_NONE               = 0,
+    HDCP_AUTHENTICATION_STEP_1                  = 1,
+    HDCP_AUTHENTICATION_STEP_2                  = 2,
+} hdcp_authentication_step_t;
+
+// KSV_GET
+typedef struct _aksv_get {
+    uint8_t                       uc_aksv[CP_HDCP_KEY_SELECTION_VECTOR_SIZE];
+} aksv_get_t;
+
+int hdcp_init(void **data, int drmFD, int output_id);
+int hdcp_uninit(void * data);
+#endif /* MDFLD_HDCP_H */
diff --git a/drivers/staging/mrst/drv/mdfld_hdcp_if.h b/drivers/staging/mrst/drv/mdfld_hdcp_if.h
new file mode 100644 (file)
index 0000000..49f06f8
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *     jim liu <jim.liu@intel.com>
+ */
+
+
+#ifndef MDFLD_HDCP_IF_H
+#define MDFLD_HDCP_IF_H
+
+// Constants
+#define CP_HDCP_KEY_SELECTION_VECTOR_SIZE       5
+
+// Protection level (HDCP)
+typedef enum _cp_protection_level_hdcp {
+    CP_PROTECTION_LEVEL_HDCP_OFF                = 0,
+    CP_PROTECTION_LEVEL_HDCP_ON                 = 1,
+} cp_protection_level_hdcp_t;
+
+// Protection type
+typedef enum _cp_protection_type {
+    CP_PROTECTION_TYPE_UNKNOWN                  = 0x80000000,
+    CP_PROTECTION_TYPE_NONE                     = 0x00000000,
+    CP_PROTECTION_TYPE_HDCP                     = 0x00000001,
+    CP_PROTECTION_TYPE_MASK                     = 0x80000001,
+} cp_protection_type_t;
+
+typedef enum _cp_status {
+    STATUS_UNSUCCESSFUL                  = 0x80000000,
+    STATUS_SUCCESS                       = 0x00000000,
+    STATUS_NOT_SUPPORTED                 = 0x00000001,
+    STATUS_INVALID_DEVICE_REQUEST        = 0x00000002,
+    STATUS_REVOKED_HDCP_DEVICE_ATTACHED  = 0x00000003,
+    STATUS_DATA_ERROR                    = 0x00000004,
+    STATUS_PENDING                       = 0x00000005,
+    STATUS_INVALID_PARAMETER             = 0x00000006,
+} cp_status_t;
+
+// KSV
+typedef struct _ksv_t {
+    uint8_t                     ab_ksv[CP_HDCP_KEY_SELECTION_VECTOR_SIZE];
+} ksv_t;
+
+// HDCP
+typedef struct _hdcp_data {
+    uint32_t                    ksv_list_length;    // Length of the revoked KSV list (set)
+    //ksv_t                       aksv;               // KSV of attached device
+    //ksv_t                       bksv;               // KSV of attached device
+    ksv_t *                     ksv_list;           // List of revoked KSVs (set)
+    int                         perform_second_step; // True when the second authentication step is requested (get)
+    int                         is_repeater;        // True when a repeater is attached to the connector (get and set)
+} hdcp_data_t;
+
+// CP Parameters
+typedef struct _cp_parameters {
+    uint32_t                    protect_type_mask;  // Protection type mask (get and set)
+    uint32_t                    level;              // Protection level (get and set)
+    hdcp_data_t                 hdcp;           // HDCP specific data (get and set)
+} cp_parameters_t;
+
+extern uint32_t hdcp_set_cp_data(cp_parameters_t* cp);
+extern uint32_t hdcp_get_cp_data(cp_parameters_t* cp);
+void mdfld_hdcp_init(struct mid_intel_hdmi_priv *p_hdmi_priv);
+
+#endif /* MDFLD_HDCP_IF_H */
diff --git a/drivers/staging/mrst/drv/mdfld_hdcp_reg.h b/drivers/staging/mrst/drv/mdfld_hdcp_reg.h
new file mode 100644 (file)
index 0000000..42b6a1f
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *     jim liu <jim.liu@intel.com>
+ */
+
+#ifndef MDFLD_HDCP_REG_H
+#define MDFLD_HDCP_REG_H
+
+/* Integrated HDMI specific registers */
+
+#define RESERVED2(x,y)  x##y
+#define RESERVED1(x,y)  RESERVED2(x,y)
+#define RANDOMNUMBER   __LINE__        // __COUNTER__
+#define UNIQUENAME(ValueName) RESERVED1(ValueName, RANDOMNUMBER)
+
+/* TBD: This may change when tested on actual system */
+#define HDCP_MAX_RI_QUERY_COUNT 4
+#define HDCP_MAX_NUM_DWORDS 4 //128 bits
+#define HDCP_MAX_RANDOMNUM_LENGTH 2 //In DWORD => 64 bits
+#define HDCP_MAX_RETRY_DISABLE 2
+/*All sizes are defined in bytes */
+#define HDCP_SIZEOF_AKSV    8 
+#define HDCP_SIZEOF_BKSV    8
+#define HDCP_SIZEOF_AN        5
+#define HDCP_SIZEOF_RI        2
+#define HDCP_ENCRYPTED_KEY_SIZE 12 //Akeys, IV and MAC
+#define HDCP_NUM_AKEYS 40
+#define HDCP_NEXT_RI_FRAME 126
+#define HDCP_MAX_RANDOM_NUM_SIZE 4//in dwords
+
+#define HDCP_CONVERT_BIG_ENDIAN(x) (((x&0x000000ff)<<24)|\
+                                    ((x&0x0000ff00)<<8)|\
+                                    ((x&0x00ff0000)>>8)|\
+                                    ((x&0xff000000)>>24))
+
+#define HDCP_MAX_AN_RETRY 100
+
+#define HDCP_AN_LO_INDEX 0
+#define HDCP_AN_HI_INDEX 1
+
+static uint32_t hdcp_invalid_an_list[6][2] =
+{
+    {0x881cf9e4, 0x38155bf4},
+    {0xb0e81640, 0xb5cac2ec},
+    {0x514fa3e7, 0x5bbb3806},
+    {0xd1b4923a, 0x6172afbb},
+    {0x0c16fd1c, 0x1b28baf5},
+    {0x00000000, 0x00000000}
+};
+
+/* HDMI HDCP Regs */
+/* HDCP config */
+
+typedef enum _mdfld_hdcp_config_enum {
+    HDCP_Off = 0,
+    HDCP_CAPTURE_AN = 1,
+    HDCP_DECRYPT_KEYS = 2,
+    HDCP_AUTHENTICATE_AND_ENCRYPT = 3,
+    HDCP_UNIQUE_MCH_ID = 5,
+    HDCP_ENCRYPT_KEYS = 6,
+    HDCP_CYPHER_CHECK_MODE = 7
+} mdfld_hdcp_config_en;
+
+#define MDFLD_HDCP_CONFIG_REG 0x61400
+    #define MDFLD_HDCP_CONFIG_PRESERVED_BITS    BITRANGE(3,31)
+typedef union _mdfld_hdcp_config {
+    uint32_t value;
+
+    struct{
+        uint32_t hdcp_config : 3; //bit 2:0; uses HDCP_CONFIGURATION_EN
+        uint32_t UNIQUENAME(Reserved): 29;//bit 3:31
+    };
+} mdfld_hdcp_config_t;
+
+
+/* HDCP_STATUS */
+
+#define MDFLD_HDCP_STATUS_REG 0x61448
+    #define MDFLD_HDCP_STATUS_PRESERVED_BITS    BITRANGE(24,31)
+typedef union _mdfld_hdcp_status {
+    uint32_t value;
+    
+    struct{
+        uint32_t ainfo                : 8; //Bit 7:0
+        uint32_t frame_count            : 8; //Bit 15:8
+        uint32_t cipher_hdcp_status    : 1; //Bit 16
+        uint32_t cipher_an_status        : 1; //Bit 17
+        uint32_t cipher_ri_ready_status    : 1; //Bit 18
+        uint32_t cipher_ri_match_status    : 1; //Bit 19
+        uint32_t cipher_encrypting_status : 1; //Bit 20
+        uint32_t cipher_ready_for_encryption : 1; //Bit 21
+        uint32_t cipher_mch_id_ready    : 1; //Bit 22
+        uint32_t cipher_mac_status        : 1; //Bit 23
+        uint32_t UNIQUENAME(Reserved)    : 8; //Bit 31:24
+    };
+} mdfld_hdcp_status_t;
+
+
+/* HDCP_RI */
+#define MDFLD_HDCP_RECEIVER_RI_REG 0x61418
+    #define MDFLD_HDCP_RECEIVER_RI_PRESERVED_BITS    BITRANGE(16,31)
+typedef union _mdfld_hdcp_receiver_ri {
+    uint32_t value;
+
+    struct{
+        uint32_t ri                    : 16; //bit 15:0
+        uint32_t UNIQUENAME(Reserved)    : 16; //bit 31:16
+    };
+} mdfld_hdcp_receiver_ri_t;
+
+
+/* HDCP_BKSV_HI */
+#define MDFLD_HDCP_BKSV_HI_REG 0x6140C
+    #define MDFLD_HDCP_BKSV_HI_PRESERVED_BITS BITRANGE(8,31)  
+typedef union _mdfld_hdcp_bksv_hi {
+    uint32_t value;
+
+    struct{
+        uint32_t bksv_hi                : 8;  //bit 7:0
+        uint32_t UNIQUENAME(Reserved)    : 24; //bit 31:8
+    };
+} mdfld_hdcp_bksv_hi_t;
+
+
+/* HDCP_AKEY_HI */
+#define MDFLD_HDCP_AKEY_HI_REG 0x61424
+    #define MDFLD_HDCP_AKEY_HI_PRESERVED_BITS BITRANGE(20,31)  
+typedef union _mdfld_hdcp_akey_hi {
+    uint32_t value;
+
+    struct{
+        uint32_t akey_hi                : 20;  //bit 7:0
+        uint32_t UNIQUENAME(Reserved)    : 12; //bit 31:8
+    };
+} mdfld_hdcp_akey_hi_t;
+
+
+
+/* HDCP_REP: Repeator specific register definitions */
+
+/* Repeater Control register */
+typedef enum _mdfld_hdcp_repeater_status_enum {
+    HDCP_REPEATER_STATUS_IDLE = 0,
+    HDCP_REPEATER_STATUS_BUSY = 1,
+    HDCP_REPEATER_STATUS_RDY_NEXT_DATA = 2,
+    HDCP_REPEATER_STATUS_COMPLETE_NO_MATCH = 4,
+    HDCP_REPEATER_STATUS_COMPLETE_MATCH = 12
+} mdfld_hdcp_repeater_status_en;
+
+typedef enum _mdfld_hdcp_repeater_ctrl_enum {
+    HDCP_REPEATER_CTRL_IDLE = 0,
+    HDCP_REPEATER_32BIT_TEXT_IP = 1,
+    HDCP_REPEATER_COMPLETE_SHA1 = 2,
+    HDCP_REPEATER_24BIT_TEXT_8BIT_MO_IP = 4,
+    HDCP_REPEATER_16BIT_TEXT_16BIT_MO_IP = 5,
+    HDCP_REPEATER_8BIT_TEXT_24BIT_MO_IP = 6,
+    HDCP_REPEATER_32BIT_MO_IP = 7
+} mdfld_hdcp_repeater_ctrl_en;
+
+#define MDFLD_HDCP_REP_REG 0x61444
+    #define MDFLD_HDCP_REP_PRESERVED_BITS BITRANGE(8,31)  
+typedef union _mdfld_hdcp_rep {
+    uint32_t value;
+
+    struct{
+        uint32_t repeater_present        : 1; //bit 0
+        uint32_t repeater_control    : 3; //bit 3:1
+        uint32_t UNIQUENAME(Reserved)    : 12; //bit 15:4 BUN#: 07ww44#1
+        const uint32_t repeater_status : 4; //bit 19:16
+        uint32_t UNIQUENAME(Reserved)    : 12;//bit 31:20
+    };
+} mdfld_hdcp_rep_t;
+
+/* HDCP_BKSV_HI */
+#define MDFLD_HDCP_AKSV_HI_REG 0x61450
+    #define MDFLD_HDCP_AKSV_HI_PRESERVED_BITS BITRANGE(8,31)  
+typedef union _mdfld_hdcp_aksv_hi {
+    uint32_t value;
+
+    struct{
+        uint32_t aksv_hi                : 8;  //bit 7:0
+        uint32_t UNIQUENAME(Reserved)    : 24; //bit 31:8
+    };
+} mdfld_hdcp_aksv_hi_t;
+
+typedef union _mdfld_hdcp_aksv {
+    uint8_t byte[8];
+
+    struct {
+        uint32_t low;
+        mdfld_hdcp_aksv_hi_t hi;
+    } aksv;
+} mdfld_hdcp_aksv_t;
+
+/* These holds part of the hash result from the receiver used for repeaters */
+#define MDFLD_HDCP_VPRIME_H0 0x6142C
+#define MDFLD_HDCP_VPRIME_H1 0x61430
+#define MDFLD_HDCP_VPRIME_H2 0x61434
+#define MDFLD_HDCP_VPRIME_H3 0x61438
+#define MDFLD_HDCP_VPRIME_H4 0x6143C
+
+#define MDFLD_HDCP_SHA1_IN    0x61440
+
+
+
+/* Define of registers that don't need register definitions */
+#define MDFLD_HDCP_INIT_REG 0x61404
+#define MDFLD_HDCP_AN_LOW_REG 0x61410
+#define MDFLD_HDCP_AN_HI_REG 0x61414
+#define MDFLD_HDCP_BKSV_LOW_REG 0x61408
+#define MDFLD_HDCP_AKSV_LOW_REG 0x61454
+/* Akey registers */
+#define MDFLD_HDCP_AKEY_LO_REG 0x6141C
+#define MDFLD_HDCP_AKEY_MED_REG 0x61420
+
+#endif /* MDFLD_HDCP_REG_H */
diff --git a/drivers/staging/mrst/drv/mdfld_hdmi_audio.c b/drivers/staging/mrst/drv/mdfld_hdmi_audio.c
new file mode 100644 (file)
index 0000000..5a2d9df
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *     jim liu <jim.liu@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_hdmi_reg.h"
+#include "psb_intel_hdmi_edid.h"
+#include "psb_intel_hdmi.h"
+#include "mdfld_hdmi_audio_if.h"
+
+
+/*
+ * Audio register range 0x69000 to 0x69117
+ */
+
+#define IS_HDMI_AUDIO_REG(reg) ((reg >= 0x69000) && (reg < 0x69118))
+
+/*
+ *
+ */
+static struct mid_intel_hdmi_priv *hdmi_priv;
+
+void mdfld_hdmi_audio_init(struct mid_intel_hdmi_priv *p_hdmi_priv)
+{
+       hdmi_priv = p_hdmi_priv;
+}
+
+/**
+ * mdfld_hdmi_audio_write:
+ * used to write into display controller HDMI audio registers.
+ *
+ */
+static int mdfld_hdmi_audio_write (uint32_t reg, uint32_t val)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    int ret = 0;
+
+    if (IS_HDMI_AUDIO_REG(reg)) {
+       REG_WRITE(reg, val);
+    } else {
+        ret = -EINVAL;
+    }
+
+    return ret;
+}
+
+/**
+ * mdfld_hdmi_audio_read:
+ * used to get the register value read from display controller HDMI audio registers.
+ *
+ */
+static int mdfld_hdmi_audio_read (uint32_t reg, uint32_t *val)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    int ret = 0;
+
+    if (IS_HDMI_AUDIO_REG(reg)) {
+       *val = REG_READ(reg);
+    } else {
+        ret = -EINVAL;
+    }
+
+    return ret;
+}
+
+/**
+ * mdfld_hdmi_audio_rmw:
+ * used to update the masked bits in display controller HDMI audio registers .
+ *
+ */
+static int mdfld_hdmi_audio_rmw (uint32_t reg, uint32_t val, uint32_t mask) 
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    int ret = 0;
+    uint32_t val_tmp = 0;
+
+    if (IS_HDMI_AUDIO_REG(reg)) {
+        val_tmp = (val & mask) | (REG_READ(reg) & ~mask); 
+       REG_WRITE(reg, val_tmp);
+    } else {
+        ret = -EINVAL;
+    }
+
+    return ret;
+}
+
+/**
+ * mdfld_hdmi_audio_get_caps:
+ * used to return the HDMI audio capabilities.
+ * e.g. resolution, frame rate.
+ */
+static int mdfld_hdmi_audio_get_caps (enum had_caps_list get_element, void *capabilities) {
+    struct drm_device *dev = hdmi_priv->dev;
+    struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+    int ret = 0;
+
+    PSB_DEBUG_ENTRY("\n");
+
+    switch (get_element) {
+    case HAD_GET_ELD:
+        memcpy(capabilities, &(hdmi_priv->eeld), sizeof(hdmi_eeld_t));
+        break;
+    case HAD_GET_SAMPLING_FREQ:
+        memcpy(capabilities, &(dev_priv->tmds_clock_khz), sizeof(uint32_t));
+        break;
+    default:
+        break;
+    }
+
+    return ret;
+}
+
+/**
+ * mdfld_hdmi_audio_set_caps:
+ * used to set the HDMI audio capabilities.
+ * e.g. Audio INT.
+ */
+static int mdfld_hdmi_audio_set_caps (enum had_caps_list set_element, void *capabilties) {
+    struct drm_device *dev = hdmi_priv->dev;
+    struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+    int ret = 0;
+    u32 hdmib;
+    u32 int_masks = 0;
+
+    PSB_DEBUG_ENTRY("\n");
+
+    switch (set_element) {
+    case HAD_SET_ENABLE_AUDIO:
+        hdmib = REG_READ(hdmi_priv->hdmib_reg);
+
+        if ((hdmib & HDMIB_PORT_EN) && hdmi_priv->has_hdmi_sink)
+            hdmib |= HDMI_AUDIO_ENABLE;
+
+        REG_WRITE(hdmi_priv->hdmib_reg, hdmib);
+        REG_READ(hdmi_priv->hdmib_reg);
+        break;
+    case HAD_SET_DISABLE_AUDIO:
+        hdmib = REG_READ(hdmi_priv->hdmib_reg) & ~HDMI_AUDIO_ENABLE;
+        REG_WRITE(hdmi_priv->hdmib_reg, hdmib);
+        REG_READ(hdmi_priv->hdmib_reg);
+        break;
+    case HAD_SET_ENABLE_AUDIO_INT:
+        if (*((u32*)capabilties) & HDMI_AUDIO_UNDERRUN)
+            int_masks |= PIPE_HDMI_AUDIO_UNDERRUN;
+
+        if (*((u32*)capabilties) & HDMI_AUDIO_BUFFER_DONE)
+            int_masks |= PIPE_HDMI_AUDIO_BUFFER_DONE;
+
+        if (dev_priv->hdmi_audio_interrupt_mask != int_masks) {
+            dev_priv->hdmi_audio_interrupt_mask |= int_masks;
+            mdfld_irq_enable_hdmi_audio(dev);
+        }
+
+        break;
+    case HAD_SET_DISABLE_AUDIO_INT:
+        if (*((u32*)capabilties) & HDMI_AUDIO_UNDERRUN)
+            int_masks |= PIPE_HDMI_AUDIO_UNDERRUN;
+
+        if (*((u32*)capabilties) & HDMI_AUDIO_BUFFER_DONE)
+            int_masks |= PIPE_HDMI_AUDIO_BUFFER_DONE;
+
+        if (dev_priv->hdmi_audio_interrupt_mask & int_masks) {
+            dev_priv->hdmi_audio_interrupt_mask &= ~int_masks;
+       
+            if (dev_priv->hdmi_audio_interrupt_mask)
+                mdfld_irq_enable_hdmi_audio(dev);
+            else
+                mdfld_irq_disable_hdmi_audio(dev);
+        }
+
+        break;
+    default:
+        break;
+    }
+
+    return ret;
+}
+
+static struct  hdmi_audio_registers_ops mdfld_hdmi_audio_reg_ops = {
+       .hdmi_audio_read_register = mdfld_hdmi_audio_read,
+       .hdmi_audio_write_register = mdfld_hdmi_audio_write,
+       .hdmi_audio_read_modify = mdfld_hdmi_audio_rmw, 
+};
+
+static struct hdmi_audio_query_set_ops mdfld_hdmi_audio_get_set_ops = {
+       .hdmi_audio_get_caps = mdfld_hdmi_audio_get_caps, 
+       .hdmi_audio_set_caps = mdfld_hdmi_audio_set_caps,
+};
+
+int intel_hdmi_audio_query_capabilities (had_event_call_back audio_callbacks, struct hdmi_audio_registers_ops *reg_ops,struct hdmi_audio_query_set_ops *query_ops) {
+    struct drm_device *dev = hdmi_priv->dev;
+    struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+    int ret = 0;
+
+    reg_ops->hdmi_audio_read_register = (mdfld_hdmi_audio_reg_ops.hdmi_audio_read_register);
+    reg_ops->hdmi_audio_write_register = (mdfld_hdmi_audio_reg_ops.hdmi_audio_write_register);
+    reg_ops->hdmi_audio_read_modify = (mdfld_hdmi_audio_reg_ops.hdmi_audio_read_modify);
+    query_ops->hdmi_audio_get_caps = mdfld_hdmi_audio_get_set_ops.hdmi_audio_get_caps;
+    query_ops->hdmi_audio_set_caps = mdfld_hdmi_audio_get_set_ops.hdmi_audio_set_caps;
+
+#if 0
+    *reg_ops = &mdfld_hdmi_audio_reg_ops; 
+    *query_ops = &mdfld_hdmi_audio_get_set_ops;
+#endif
+    dev_priv->mdfld_had_event_callbacks = audio_callbacks;
+
+    return ret;
+}
+
+int display_register(struct snd_intel_had_interface *driver, void * had_data)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+       dev_priv->had_pvt_data = had_data;
+       dev_priv->had_interface = driver;
+       return 0;
+}
+
+#if 0
+EXPORT_SYMBOL(intel_hdmi_audio_query_capabilities); 
+EXPORT_SYMBOL(display_register); 
+#endif
diff --git a/drivers/staging/mrst/drv/mdfld_hdmi_audio_if.h b/drivers/staging/mrst/drv/mdfld_hdmi_audio_if.h
new file mode 100644 (file)
index 0000000..e5ece79
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *     jim liu <jim.liu@intel.com>
+ */
+
+
+#ifndef MDFLD_HDMI_AUDIO_IF_H
+#define MDFLD_HDMI_AUDIO_IF_H
+
+#include "psb_intel_hdmi.h"
+
+/* HDMI AUDIO INTERRUPT TYPE */
+#define HDMI_AUDIO_UNDERRUN    (1UL<<0)
+#define HDMI_AUDIO_BUFFER_DONE (1UL<<1)
+
+enum had_caps_list {
+       HAD_GET_ELD = 1,
+       HAD_GET_SAMPLING_FREQ,
+       HAD_GET_DISPLAY_RATE,
+       HAD_GET_HDCP_STATUS,
+       HAD_GET_AUDIO_STATUS,
+       HAD_SET_ENABLE_AUDIO,
+       HAD_SET_DISABLE_AUDIO,
+        HAD_SET_ENABLE_AUDIO_INT,
+        HAD_SET_DISABLE_AUDIO_INT,
+       OTHERS_TBD,
+};
+
+enum had_event_type {
+       HAD_EVENT_HOT_PLUG = 1,
+       HAD_EVENT_HOT_UNPLUG,
+       HAD_EVENT_MODE_CHANGING,
+       HAD_EVENT_PM_CHANGING,
+       HAD_EVENT_AUDIO_BUFFER_DONE,
+       HAD_EVENT_AUDIO_BUFFER_UNDERRUN,
+};
+
+/**
+ * HDMI Display Controller Audio Interface 
+ * 
+ */
+typedef int (*had_event_call_back)(enum had_event_type event_type, void * ctxt_info);
+
+struct  hdmi_audio_registers_ops{
+       int (*hdmi_audio_read_register)(uint32_t reg_addr, uint32_t *data);
+       int (*hdmi_audio_write_register) (uint32_t reg_addr, uint32_t data);
+       int (*hdmi_audio_read_modify)(uint32_t reg_addr, uint32_t data, uint32_t mask);
+};
+
+struct hdmi_audio_query_set_ops{
+       int (*hdmi_audio_get_caps)(enum had_caps_list query_element , void *capabilties);
+       int (*hdmi_audio_set_caps)(enum had_caps_list set_element , void *capabilties);
+};
+
+typedef struct pm_event {
+       int event;
+} pm_event_t;
+struct snd_intel_had_interface {
+        const char *name;
+        int (*probe) (void *had_data,
+                      const int card_id);
+        void (*disconnect) (void *had_data);
+        int (*suspend) (void *had_data, pm_event_t event);
+        int (*resume) (void *had_data);
+
+};
+
+extern int intel_hdmi_audio_query_capabilities (had_event_call_back audio_callbacks, struct hdmi_audio_registers_ops *reg_ops,struct hdmi_audio_query_set_ops *query_ops);
+extern  int display_register(struct snd_intel_had_interface *driver,void * had_data);
+
+void mdfld_hdmi_audio_init(struct mid_intel_hdmi_priv *p_hdmi_priv);
+
+#endif /* MDFLD_HDMI_AUDIO_IF_H */
diff --git a/drivers/staging/mrst/drv/mdfld_intel_hdcp.c b/drivers/staging/mrst/drv/mdfld_intel_hdcp.c
new file mode 100644 (file)
index 0000000..91ac18c
--- /dev/null
@@ -0,0 +1,1351 @@
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *     jim liu <jim.liu@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_hdmi_reg.h"
+#include "psb_intel_hdmi.h"
+#include "mdfld_hdcp_if.h"
+#include "mdfld_hdcp_reg.h"
+#include "mdfld_hdcp.h"
+
+
+/*
+ *
+ */
+static struct mid_intel_hdmi_priv *hdmi_priv;
+
+void mdfld_hdcp_init(struct mid_intel_hdmi_priv *p_hdmi_priv)
+{
+       hdmi_priv = p_hdmi_priv;
+}
+
+/* 
+ * IsValidBKSV:
+ * Checks if the BKSV is valid or not.
+ * A valid BKSV is one that contains 20 0's and 20 1's
+ *
+ */
+static int hdcp_is_valid_bksv(uint8_t* buffer,uint32_t size)
+{
+    uint8_t count = 0;
+    int i =0;
+    uint8_t bksv = 0;
+    uint8_t bit = 0;
+    int ret = 0;
+
+    if(buffer == NULL || size != CP_HDCP_KEY_SELECTION_VECTOR_SIZE)
+       return ret;
+    
+    while(i<CP_HDCP_KEY_SELECTION_VECTOR_SIZE)
+    {
+        bksv=buffer[i];
+        while(bksv !=0)
+        {
+            bit = (bksv) & 0x01;
+            if(bit)
+               count++;
+            bksv = bksv >> 1;
+        }
+        i++;
+    }
+
+    if(count == 20)
+        ret = 1;
+
+    return ret;
+}
+
+/* 
+ * Gets the current status of HDCP 
+ * 
+ */
+static int hdcp_is_enabled(void)
+{
+       struct drm_device *dev = hdmi_priv->dev;
+       mdfld_hdcp_status_t hdcp_status = {0};
+       int ret = 0;
+
+       if(hdmi_priv->is_hdcp_supported)
+       {
+               hdcp_status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+               ret = hdcp_status.cipher_hdcp_status;
+       }
+    
+       return ret;
+}
+
+#define HDCP_PRIMARY_I2C_ADDR 0x74
+/*
+ *
+ * Read HDCP device data from i2c link 
+ *
+ */
+static int read_hdcp_port_data(uint8_t offset, uint8_t* buffer, int size)
+{
+       struct i2c_msg msgs[] = {
+               {
+                       .addr   = HDCP_PRIMARY_I2C_ADDR,
+                       .flags  = 0,
+                       .len    = 1,
+                       .buf    = &offset,
+               }, {
+                       .addr   = HDCP_PRIMARY_I2C_ADDR,
+                       .flags  = I2C_M_RD,
+                       .len    = size,
+                       .buf    = buffer,
+               }
+       };
+
+       if (i2c_transfer(hdmi_priv->hdmi_i2c_adapter, msgs, 2) == 2)
+               return 1;
+
+       return 0;
+}
+
+/* Read device status from i2c link */
+static int read_hdcp_port(uint32_t read_request_type, uint8_t *buffer, int size)
+{
+    int more_blocks_to_read = 0;
+    uint32_t block_offset=0;
+    int ret = 1;
+    uint8_t offset = 0;
+    
+    while(1)
+    {
+        switch(read_request_type)
+        {
+        case RX_TYPE_BSTATUS:
+            offset = RX_BSTATUS_0;
+            break;
+        case RX_TYPE_RI_DATA:
+            offset = RX_RI_HIGH;
+            break;
+        case RX_TYPE_BCAPS:
+            offset = RX_BCAPS;
+            break;
+        case RX_TYPE_REPEATER_KSV_LIST:
+            offset = RX_KSV_FIFO;
+            break;
+        case RX_TYPE_BKSV_DATA:
+            offset = RX_BKSV_0;
+            break;
+        case RX_TYPE_REPEATER_PRIME_V:
+            {
+                offset = block_offset + RX_VPRIME_H0_0;
+                buffer += block_offset;
+                size = 4;
+                if(offset < RX_VPRIME_H4_0)
+                {
+                    more_blocks_to_read = 1;
+                    block_offset += 4;
+                }
+            }
+            break;
+        default:
+            ret = 0;
+            break;
+        }
+
+        if(ret)
+        {
+            if(!read_hdcp_port_data(offset, buffer, size))
+            {
+                //I2C access failed
+                ret = 0;
+                break;
+            }
+            
+            //Check whether more blocks are to be read
+            if(!more_blocks_to_read)
+            {
+                break;
+            }
+            else
+            {
+                more_blocks_to_read = 0;
+            }
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/* write to HDCP device through i2c link */
+static int write_hdcp_port(uint8_t offset, uint8_t *buffer, int size)
+{
+       struct i2c_msg msgs[] = {
+               {
+                       .addr   = HDCP_PRIMARY_I2C_ADDR,
+                       .flags  = 0,
+                       .len    = 1,
+                       .buf    = &offset,
+               }, {
+                       .addr   = HDCP_PRIMARY_I2C_ADDR,
+                       .flags  = 0,
+                       .len    = size,
+                       .buf    = buffer,
+               }
+       };
+
+       if (i2c_transfer(hdmi_priv->hdmi_i2c_adapter, msgs, 2) == 2)
+               return 1;
+
+       return 0;
+}
+
+/*
+ *
+ * UpdateRepeaterState : Enables/Disables Repeater
+ *
+ */
+static int hdcp_update_repeater_state(int enable)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    mdfld_hdcp_rep_t hdcp_rep_ctrl_reg;
+    hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+    hdcp_rep_ctrl_reg.repeater_present = enable;
+
+    REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+    return 1;
+
+}
+
+/* 
+ * EnableHDCP : Enables/Disables HDCP
+ *
+ */
+static int hdcp_enable(int enable)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    mdfld_hdcp_config_t config;
+    mdfld_hdcp_receiver_ri_t receivers_ri;
+    mdfld_hdcp_status_t status;    
+    mdfld_hdcp_rep_t hdcp_repeater;
+    uint32_t max_retry = 0;
+    sqword_t hw_an;
+    sqword_t hw_aksv;
+    sqword_t hw_bksv;
+    uint8_t bcaps=0;
+    uint32_t rx_ri = 0;
+    int ret = 0;
+
+    if(enable == 0)
+    {
+        config.value = REG_READ(MDFLD_HDCP_CONFIG_REG);
+        config.hdcp_config =  HDCP_Off;
+       REG_WRITE(MDFLD_HDCP_CONFIG_REG,config.value);
+
+        //Check the status of cipher till it get's turned off
+        // Bug #2808007-Delay required is one frame period.
+        // waiting for 2 VBlanks provides this amount of delay
+        max_retry = 0;
+        status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+        while((status.cipher_hdcp_status || status.cipher_encrypting_status) && max_retry< HDCP_MAX_RETRY_DISABLE)
+        {
+            psb_intel_wait_for_vblank(dev);
+            status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+            max_retry++;
+        }
+
+        // Check for cipher time out
+        if(status.cipher_hdcp_status || status.cipher_encrypting_status)
+        {
+            ret = 0; 
+           return ret;
+        }
+
+        // clear the repeater specfic bits and set the repeater to idle
+        hdcp_repeater.value =  REG_READ(MDFLD_HDCP_REP_REG);
+        hdcp_repeater.repeater_present = 0;
+        hdcp_repeater.repeater_control = HDCP_REPEATER_CTRL_IDLE;
+        REG_WRITE(MDFLD_HDCP_REP_REG, hdcp_repeater.value); 
+
+        max_retry = HDCP_MAX_RETRY_STATUS;//tbd: not yet finalized
+        while(max_retry--)
+        {
+            hdcp_repeater.value =  REG_READ(MDFLD_HDCP_REP_REG);
+
+            if(hdcp_repeater.repeater_status == HDCP_REPEATER_STATUS_IDLE)
+            {
+                ret = 1;
+                break;
+            }
+        }
+
+        // Check for cipher time out
+        if(max_retry == 0)
+        {
+            ret = 0; 
+           return 0;
+        }
+
+        // Clear the Ri' register
+        // This is a HW issue because of which the Ri' status bit in HDCP_STATUS
+        // register doesn't get cleared. 
+        // refer ro https://vthsd.fm.intel.com/hsd/cantiga/sighting/default.aspx?sighting_id=304464
+        // for details
+        REG_WRITE(MDFLD_HDCP_RECEIVER_RI_REG, 0);
+
+       //Disable the port on which HDCP is enabled
+       REG_WRITE(hdmi_priv->hdmib_reg, REG_READ(hdmi_priv->hdmib_reg) & ~HDMIB_HDCP_PORT);
+    }
+    else
+    {
+        //Generate An
+        config.value = REG_READ(MDFLD_HDCP_CONFIG_REG);
+
+        if (config.hdcp_config != HDCP_Off) {
+            config.hdcp_config = HDCP_Off;
+            REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value);
+        }
+  
+        /* used the jiffies as a random number. */
+        REG_WRITE(MDFLD_HDCP_INIT_REG, (uint32_t) jiffies); 
+        REG_WRITE(MDFLD_HDCP_INIT_REG, (uint32_t) (jiffies >> 1)); 
+       udelay (10);
+
+        config.hdcp_config =  HDCP_CAPTURE_AN;
+        REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value);
+            
+        //check the status of cipher before reading an
+        max_retry = HDCP_MAX_RETRY_STATUS;//tbd: not yet finalized
+        while(max_retry--)
+        {
+            status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+            if(status.cipher_an_status)
+            {
+                ret = 1;
+                break;
+            }
+        }
+            
+        config.hdcp_config = HDCP_Off;
+        REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value);
+
+        if(max_retry == 0)
+            return 0;//Cipher timeout, was not able to generate An :(
+
+        //Read An
+        hw_an.u.low_part = REG_READ(MDFLD_HDCP_AN_LOW_REG);
+        hw_an.u.high_part = REG_READ(MDFLD_HDCP_AN_HI_REG);
+                
+       hw_aksv.u.low_part = REG_READ(MDFLD_HDCP_AKSV_LOW_REG);
+       hw_aksv.u.high_part = REG_READ(MDFLD_HDCP_AKSV_HI_REG);
+        //stHdcpParams.hwAksv.MajorPart_Low = 0x0361f714;//test data
+        //stHdcpParams.hwAksv.MajorPart_High = 0xb7;
+
+        //write An
+        ret = write_hdcp_port(RX_AN_0, hw_an.byte, 8);
+        if(!ret)
+            return 0;
+
+        //write Aksv
+        ret = write_hdcp_port(RX_AKSV_0, hw_aksv.byte, 5);
+        if(!ret)
+            return 0;
+        
+        //Read the Bksv from receiver
+        ret =read_hdcp_port(RX_TYPE_BKSV_DATA, &hw_bksv.byte[0], 5);
+        if(ret)
+        {
+             // Validate BKSV
+             ret = hdcp_is_valid_bksv(&hw_bksv.byte[0], 5);
+        }
+
+         if(!ret)
+            return 0;
+
+        //read the BCaps 
+        ret = read_hdcp_port(RX_TYPE_BCAPS, &bcaps, 1);
+        if(!ret)
+            return 0;
+
+        // set repeater bit if receiver connected is a repeater
+        if(bcaps & BIT(6))
+        {
+            hdcp_update_repeater_state(1);
+        }
+
+        //Write the BKsv into the encoder
+       REG_WRITE(MDFLD_HDCP_BKSV_LOW_REG, hw_bksv.u.low_part);
+       REG_WRITE(MDFLD_HDCP_BKSV_HI_REG, hw_bksv.u.high_part);
+        //enable HDCP on this port
+       REG_WRITE(hdmi_priv->hdmib_reg, REG_READ(hdmi_priv->hdmib_reg) | HDMIB_HDCP_PORT);
+
+        //TBD :Check the bStatus, for repeater and set HDCP_REP[1]
+        //Set HDCP_CONFIG to 011 = Authenticate and encrypt
+        config.hdcp_config = HDCP_AUTHENTICATE_AND_ENCRYPT;
+        REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value);
+
+
+        //At this point of time the Km is created
+        
+        //Wait for Ri ready
+        max_retry = HDCP_MAX_RETRY_STATUS;//TBD: Not yet finalized
+        while(max_retry--)
+        {
+            status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+            if(status.cipher_ri_ready_status)
+                break;
+        }
+
+        if(max_retry == 0)
+            return 0;//Cipher timeout, was not able to generate An :(
+
+        //Compare the R0 and Ri
+        //Read the Ri' of reciever
+        ret = read_hdcp_port(RX_TYPE_RI_DATA, (uint8_t*)&rx_ri, 2);
+        if(!ret)
+            return 0;
+
+        //TBD:Have some delay before reading the Ri'
+        //Right now using 100 ms, as per the HDCP spec(Refer HDCP SAS for details)
+        mdelay(HDCP_100MS_DELAY);
+
+        //update the HDCP_Ri' register and read the status reg for confrmation
+        receivers_ri.value = REG_READ(MDFLD_HDCP_RECEIVER_RI_REG);
+        receivers_ri.ri = rx_ri;
+        REG_WRITE(MDFLD_HDCP_RECEIVER_RI_REG, receivers_ri.value);
+        
+        status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+
+        //SoftbiosDebugMessage(DBG_CRITICAL,"R Prime       = %x\n",dwRxRi);
+        //SoftbiosDebugMessage(DBG_CRITICAL,"HDCP_STATUS = %x\n",stStatus.value);
+        ret = status.cipher_ri_match_status;
+       /*if(GEN4INTHDCPCONTROLLER_HasInterruptOccured(pThis,ePort) == TRUE)
+       {
+               bRet = 0;
+       }*/
+    }
+
+    if(!ret)
+    {
+        //TODO: SoftbiosDebugMessage(DBG_CRITICAL," EnableHDCP failed \n");
+    }
+
+    return ret;
+}
+
+/*
+To obtain receiver specific data. The request type
+is from mdfld_hdcp_rx_data_type_en 
+*/
+static int hdcp_get_receiver_data(uint8_t* buffer, uint32_t size, uint32_t rx_data_type)
+{
+    int ret = 0;
+
+    if(buffer)
+    {
+        memset(buffer, 0, size);
+        //Get the Data from reciever
+        ret = read_hdcp_port(rx_data_type, buffer, size);
+    }
+
+    // Validate BKSV and Check if its Valid.
+    if(RX_TYPE_BKSV_DATA == rx_data_type)
+    {
+        ret = hdcp_is_valid_bksv(buffer, size);
+    }
+
+    return ret;
+}
+
+/*
+ *
+ * WaitForNextDataReady : Function Waits for enryption ready
+ *
+ */
+static int hdcp_wait_for_next_data_ready(void)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    mdfld_hdcp_rep_t hdcp_rep_reg;
+    uint32_t i = 0; 
+    int ret =  0;
+
+    for(i=0;i<HDCP_MAX_RETRY_STATUS;i++)
+    {
+        hdcp_rep_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+
+        if(HDCP_REPEATER_STATUS_RDY_NEXT_DATA == hdcp_rep_reg.repeater_status)
+        {
+            ret = 1;
+            break;
+        }
+    }
+    
+    return ret;
+}
+
+/*
+ *
+ * CompareVPrime : This routine compares the vprime
+ * obtained from receiver with the one generated in
+ * transmitter.
+ *
+ */
+static int hdcp_compare_v_prime(uint32_t* buffer_repeater_v_prime, uint8_t size_in_dword)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    uint32_t value = 0;
+    uint8_t* buffer = (uint8_t*)buffer_repeater_v_prime;
+    int ret = 0;
+    mdfld_hdcp_rep_t hdcp_rep_ctrl_reg;
+    uint32_t i = 0;
+
+    //TBD: To be implemented as part of repeater implementation
+    //Set the repeater's vprime in GMCH
+
+    if(size_in_dword == KSV_SIZE)
+    {
+        memcpy(&value,buffer,4);
+        REG_WRITE(MDFLD_HDCP_VPRIME_H0,value);
+
+        buffer += 4;
+        memcpy(&value,buffer,4);
+        REG_WRITE(MDFLD_HDCP_VPRIME_H1,value);
+
+        buffer += 4;
+        memcpy(&value,buffer,4);
+        REG_WRITE(MDFLD_HDCP_VPRIME_H2,value);
+
+        buffer += 4;
+        memcpy(&value,buffer,4);
+        REG_WRITE(MDFLD_HDCP_VPRIME_H3,value);
+
+        buffer += 4;
+        memcpy(&value,buffer,4);
+        REG_WRITE(MDFLD_HDCP_VPRIME_H4,value);
+
+        if(!hdcp_wait_for_next_data_ready())
+            return 0;
+    
+        // Set HDCP_REP to do the comparison
+        // Start transmitter's V calculation
+        hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+        hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_COMPLETE_SHA1;
+        REG_WRITE(MDFLD_HDCP_REP_REG, hdcp_rep_ctrl_reg.value);
+        
+        for(i=0;i<HDCP_MAX_RETRY_STATUS;i++)
+        {
+            hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+
+            switch(hdcp_rep_ctrl_reg.repeater_status)
+            {
+            case HDCP_REPEATER_STATUS_COMPLETE_MATCH :
+                ret = 1;
+                break;
+            case HDCP_REPEATER_STATUS_COMPLETE_NO_MATCH :
+                ret = 0;
+                break;
+            case HDCP_REPEATER_STATUS_IDLE :
+                //Should not happen
+                ret = 0;
+                break;
+            //default: Not needed
+            }
+
+            if(hdcp_rep_ctrl_reg.repeater_status != HDCP_REPEATER_STATUS_BUSY)
+            {   
+                break;
+            }
+        }
+        
+    }
+    else
+    {
+        ret = 0;
+    }
+
+    return ret;
+}
+
+/* 
+ *
+ * ComputeTransmitterV : This routine computes transmitter's V prime.
+ * As per HDCP spec 1.3 for HDMI/DVI the BStatus register contains data specific to repeater 
+ * sink topology in case sink is a repeater. The same interface is used by HDCP over display port
+ * in which case BInfo contains the relevant data. The variable wBTopologyData represents Bstatus
+ * for HDMI/DVI and BInfo for Display Port
+ *
+ */
+static int hdcp_compute_transmitter_v(ksv_t *ksv_list, uint32_t ksv_list_entries, uint16_t b_topology_data)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    uint32_t num_devices = ksv_list_entries;
+//    uint32_t lower_num_bytes_for_sha = 0, upper_num_bytes_for_sha = 0; // This has to be in mutiple of 512 bits
+    uint32_t lower_num_bytes_for_sha = 0;
+    uint32_t num_pad_bytes = 0;
+    uint8_t *buffer = NULL;
+    uint8_t *temp_buffer = NULL;
+    mdfld_hdcp_rep_t hdcp_rep_ctrl_reg;
+    uint32_t value = 0;
+    int ret = 1;
+    uint32_t i = 0;
+    uint32_t rem_text_data = 0, num_mo_bytes_left = 8;
+    uint8_t* temp_data_ptr = NULL;
+    sqword_t buffer_len;
+    uint32_t temp_data = 0;
+
+    //Clear SHA hash generator for new V calculation and set the repeater to idle state
+    REG_WRITE(MDFLD_HDCP_SHA1_IN, 0);
+    hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+    hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_CTRL_IDLE;
+    REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+    for(i=0; i<HDCP_MAX_RETRY_STATUS; i++)
+    {
+        hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+        if(HDCP_REPEATER_CTRL_IDLE == hdcp_rep_ctrl_reg.repeater_status)
+        {
+            ret = 1;
+            break;
+        }
+    }
+    if(i == HDCP_MAX_RETRY_STATUS)
+    {
+        return 0;
+    }
+
+    // Start the SHA buffer creation
+    //To find the number of pad bytes
+    num_pad_bytes = (64 - (ksv_list_entries*KSV_SIZE + 18)%64);
+
+    // Get the number of bytes for SHA
+    lower_num_bytes_for_sha = KSV_SIZE*num_devices + 18 + num_pad_bytes;//multiple of 64 bytes
+    
+    buffer = (uint8_t*)kzalloc(lower_num_bytes_for_sha, GFP_KERNEL);
+    
+    if(buffer)
+    {
+        //1. Copy the KSV buffer
+        //Note:The data is in little endian format
+        temp_buffer = buffer;
+        memcpy((void*)temp_buffer,(void*)ksv_list,num_devices*KSV_SIZE);
+        temp_buffer += num_devices*KSV_SIZE;
+
+        //2. Copy the b_topology_data
+        memcpy((void*)temp_buffer,(void*)&b_topology_data,2);
+        //The bstatus is copied in little endian format
+        temp_buffer +=2;
+
+        //3. Offset the pointer buffer by 8 bytes
+        // These 8 bytes are zeroed and are place holdes for Mo
+        temp_buffer +=8;
+
+        //4. Pad the buffer with extra bytes
+        // No need to pad the begining of padding bytes by adding
+        // 0x80. HW automatically appends the same while creating 
+        // the buffer.
+        //*temp_buffer = (BYTE)0x80;
+        //temp_buffer++;
+        for(i=0;i<num_pad_bytes;i++)
+        {
+            *temp_buffer = (uint8_t)0x00;
+            temp_buffer++;
+        }
+
+        //5. Construct the length byte
+        buffer_len.quad_part = (unsigned long long)(ksv_list_entries*KSV_SIZE + 2 + 8)*8;
+        temp_data_ptr = (uint8_t*)&buffer_len.quad_part;
+        // Store it in big endian form
+        for(i=1; i<=8; i++)
+        {
+            *temp_buffer = *(temp_data_ptr + 8-i);
+            temp_buffer++;
+        }
+
+        //5.Write a random 64 bit value to the buffer
+        //memcpy(temp_buffer,&upper_num_bytes_for_sha,4);
+        //temp_buffer += 4;
+        //memcpy(temp_buffer,&lower_num_bytes_for_sha,4);
+        
+        //Now write the data into the SHA
+        temp_buffer = buffer;
+        for(i=0; i<(KSV_SIZE*num_devices + 2)/4; i++)
+        {
+            hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+            hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_32BIT_TEXT_IP;
+            REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+
+            //As per HDCP spec sample SHA is in little endian format. But the
+            //data fed to the cipher needs to be in big endian format for it
+            //to compute it correctly
+            memcpy(&value,temp_buffer,4);
+            value = HDCP_CONVERT_BIG_ENDIAN(value);
+            REG_WRITE(MDFLD_HDCP_SHA1_IN, value);
+            temp_buffer += 4;
+
+            if(!hdcp_wait_for_next_data_ready())
+                return 0;
+        }
+
+        //Write the remaining text data with M0 
+        //BUN#: 07ww44#1: text input must be aligned to LSB of the SHA1 
+        //in register when inputting partial text and partial M0
+        rem_text_data = (KSV_SIZE*num_devices + 2)%4;
+        if(rem_text_data)
+        {
+            // Update the no of Mo bytes
+            num_mo_bytes_left = num_mo_bytes_left - (4-rem_text_data);
+
+            if(!hdcp_wait_for_next_data_ready())
+                return 0;
+
+            hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+            switch(rem_text_data)
+            {
+            case 1:
+                hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_8BIT_TEXT_24BIT_MO_IP;
+                break;
+            case 2:
+                hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_16BIT_TEXT_16BIT_MO_IP;
+                break;
+            case 3:
+                hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_24BIT_TEXT_8BIT_MO_IP;
+                break;
+            default:
+                ret = 0;
+            }
+            
+            if(!ret)
+                return ret;
+                
+            REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+            memcpy(&value,temp_buffer,4);
+
+            // swap the text data in big endian format leaving the Mo data as it is.
+            // As per the bun the LSB should contain the data in big endian format.
+            // since the M0 specfic data is all zeros while it's fed to the cipher.
+            // Those bit don't need to be modified
+            temp_data = 0;
+            for(i=0; i<rem_text_data; i++)
+            {
+                temp_data |= ((value & 0xff<<(i*8))>>(i*8))<<((rem_text_data - i-1)*8);
+            }
+            REG_WRITE(MDFLD_HDCP_SHA1_IN, temp_data);
+            temp_buffer += 4;
+        }
+        
+        //Write 4 bytes of Mo
+        if(!hdcp_wait_for_next_data_ready())
+             return 0;
+
+        hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+        hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_32BIT_MO_IP;
+        REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+        memcpy(&value,temp_buffer,4);
+        REG_WRITE(MDFLD_HDCP_SHA1_IN, value);
+        temp_buffer += 4;
+        num_mo_bytes_left -= 4;
+
+        if(num_mo_bytes_left)
+        {
+            // The remaining Mo + padding bytes need to be added 
+            num_pad_bytes = num_pad_bytes - (4-num_mo_bytes_left);
+
+            //Write 4 bytes of Mo
+            if(!hdcp_wait_for_next_data_ready())
+                return 0;
+
+            hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+            switch(num_mo_bytes_left)
+            {
+                case 1:
+                    hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_24BIT_TEXT_8BIT_MO_IP;
+                    break;
+                case 2:
+                    hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_16BIT_TEXT_16BIT_MO_IP;
+                    break;
+                case 3:
+                hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_8BIT_TEXT_24BIT_MO_IP;
+                break;
+                default:
+                // should never happen
+                ret = 0;
+            }
+
+            if(!ret)
+                return ret;
+                
+            REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+            memcpy(&value,temp_buffer,4);
+            //BUN#:07ww44#1
+            temp_data = 0;
+            for(i=0; i<rem_text_data; i++)
+            {
+                temp_data |= ((value & 0xff<<(i*8))>>(i*8))<<((rem_text_data - i-1)*8);
+            }
+            REG_WRITE(MDFLD_HDCP_SHA1_IN, value);
+            temp_buffer += 4;
+            num_mo_bytes_left = 0;
+        }
+
+        //Write the remaining no of bytes
+        // Remaining data = remaining padding data + 64 bits of length data
+        rem_text_data = num_pad_bytes + 8;
+
+        if(rem_text_data%4)
+        {
+            //Should not happen
+            return 0;
+        }
+        
+        for(i=0;i<rem_text_data/4;i++)
+        {
+            REG_WRITE(MDFLD_HDCP_SHA1_IN,temp_data);
+            if(!hdcp_wait_for_next_data_ready())
+                return 0;
+
+            hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+            hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_32BIT_TEXT_IP;
+            REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+            memcpy(&value,temp_buffer,4);
+            // do the Big endian conversion
+            value = HDCP_CONVERT_BIG_ENDIAN(value);
+            REG_WRITE(MDFLD_HDCP_SHA1_IN, value);
+            temp_buffer += 4;
+        }
+        kfree(buffer);
+
+        ret = 1;    
+    }
+    else
+    {
+        return 0;
+    }
+
+    return ret;
+}
+
+/*
+ *
+ * SetHDCPEncryptionLevel:
+ *
+ */
+static uint32_t hdcp_set_encryption_level(cp_parameters_t* cp)
+{
+    uint32_t ret = STATUS_UNSUCCESSFUL;
+    int hdcp_enabled = 0;
+    uint32_t ksv_length = 0;
+    ksv_t bksv;
+
+    //Get the hdcp configuration of the port
+    if(hdmi_priv->is_hdcp_supported)
+    {
+        hdcp_enabled = hdcp_is_enabled();
+        if(((cp->level == CP_PROTECTION_LEVEL_HDCP_OFF)&&(!hdcp_enabled))||
+           ((cp->level == CP_PROTECTION_LEVEL_HDCP_ON)&&hdcp_enabled))
+        {
+            ret = STATUS_SUCCESS;
+        }
+
+        if(ret == STATUS_UNSUCCESSFUL)
+        {
+            //Turn off HDCP
+            if (hdcp_enable(0))
+                ret = STATUS_SUCCESS;
+            
+            if((cp->level != CP_PROTECTION_LEVEL_HDCP_OFF) && (ret == STATUS_SUCCESS))
+            {
+                // Check if a Revoked device is attached
+                if(cp->hdcp.ksv_list_length)
+                {
+                    //Get the current set of BKSV's from the 
+                    if(hdcp_get_receiver_data((uint8_t*)bksv.ab_ksv, CP_HDCP_KEY_SELECTION_VECTOR_SIZE, RX_TYPE_BKSV_DATA))
+                    {
+                         for(ksv_length = 0; ksv_length<cp->hdcp.ksv_list_length; ksv_length++)
+                         {
+                             if(!memcmp(&bksv,
+                                        &cp->hdcp.ksv_list[ksv_length],
+                                         CP_HDCP_KEY_SELECTION_VECTOR_SIZE))
+                              {
+                                  ret = STATUS_REVOKED_HDCP_DEVICE_ATTACHED;
+                                  break; 
+                                   
+                              }
+                          }
+                     }
+                }
+                
+
+                if(ret == STATUS_SUCCESS)
+                {
+                    //Activate the link layer
+                    ret = hdcp_enable(1);
+                }
+                
+            }
+        }
+    }
+    return ret;
+}
+
+/*
+ *
+ * GetMaxSupportedAttachedDevices: Returns the
+ * max no attached devices supported on repeater 
+ *
+ */
+static uint16_t hdcp_get_max_supported_attached_devices(void)
+{
+    //currently return 128 as specified by the HDCP spec
+    return MAX_HDCP_DEVICES;
+}
+
+/*
+ *
+ * ActivateRepeater: Activates reciver mode
+ *
+ */
+static uint32_t hdcp_activate_repeater(cp_parameters_t* cp)
+{
+    uint32_t ret = STATUS_UNSUCCESSFUL;
+    uint16_t device_count = 0;
+    uint16_t get_max_device_supported = 0;
+    uint8_t* ksv_list=NULL;//[MAX_HDCP_DEVICES] = {0};// * KSV_SIZE] = { 0 };
+    uint16_t i = 0, j = 0, k = 0;
+    uint32_t repeater_prime_v[5];
+    hdcp_rx_bcaps_t b_caps;
+    hdcp_rx_bstatus_t b_status;
+    //TBD: TO be enabled for OPM - Vista
+    
+    // Init bcaps
+    b_caps.value = 0;
+    b_status.value = 0;
+    
+    for(i = 0; i<5; i++)
+        repeater_prime_v[i] = 0;
+
+    for(i=0;i<1;i++)
+    {
+        ksv_list = (uint8_t*)kzalloc(MAX_HDCP_DEVICES*KSV_SIZE, GFP_KERNEL);
+
+        if(!ksv_list)
+        {
+            ret = STATUS_UNSUCCESSFUL;        
+            break;
+        }
+
+        //get the receiver bcaps 
+        hdcp_get_receiver_data(&b_caps.value, 1, RX_TYPE_BCAPS);
+
+        // Check for repeater caps
+        if(!(b_caps.is_reapeater))
+        {    
+            ret = STATUS_INVALID_PARAMETER;
+            break;
+        }
+        
+        // Check if the KSV FIFO is ready
+        if(!(b_caps.ksv_fifo_ready))
+        {
+            // The HDCP repeater is not yet ready to return a KSV list.
+            // Per HDCP spec, the repeater has 5 seconds from when KSVs are exchanged
+            // in the first part of the authentication protocol (HDCPActivateLink)
+            // to be ready to report out downstream KSVs.
+            ret = STATUS_PENDING;
+            break;
+        }
+    
+        //Read repeater's Bstatus
+        hdcp_get_receiver_data((uint8_t*)&b_status.value, 2, RX_TYPE_BSTATUS);
+        
+        // check if max dev limit is exceeded
+        if(b_status.max_devs_exceeded)
+        {
+            ret = STATUS_INVALID_PARAMETER;
+            break;
+        }
+        
+        // Check for topology error. This happens when
+        // more then seven levels of video repeater have been cascaded.
+        if(b_status.max_cascade_exceeded)
+        {
+            ret =  STATUS_INVALID_PARAMETER;
+            break;
+        }
+        
+        device_count = b_status.device_count;
+        if(device_count == 0)
+        {
+            ret = STATUS_SUCCESS;
+            break;
+        }
+
+        get_max_device_supported = hdcp_get_max_supported_attached_devices();
+        
+        if(device_count > get_max_device_supported)
+        {
+            ret =  STATUS_INVALID_PARAMETER;
+            break;
+        }
+        
+        // Update the cipher saying sink supports repeater capabilities
+        if(!hdcp_update_repeater_state(1))
+        {
+            ret = STATUS_UNSUCCESSFUL;
+            break;
+        }
+
+        // Read the KSV list from the repeater
+        if(!hdcp_get_receiver_data(ksv_list, device_count * KSV_SIZE, RX_TYPE_REPEATER_KSV_LIST))
+        {
+            ret = STATUS_UNSUCCESSFUL;
+            break;
+        }
+        
+        for(j=0; j<device_count; j++)
+        {
+            for(k=0; k<cp->hdcp.ksv_list_length; k++)
+            {
+                if(0==memcmp(&ksv_list[j* KSV_SIZE], &cp->hdcp.ksv_list[k], CP_HDCP_KEY_SELECTION_VECTOR_SIZE))
+                {
+                    ret =    STATUS_REVOKED_HDCP_DEVICE_ATTACHED;
+                    break;
+                }
+            }
+        }
+        
+        if(!hdcp_compute_transmitter_v((ksv_t *)ksv_list,device_count,b_status.value))
+        {
+            ret = STATUS_UNSUCCESSFUL;
+            break;
+        }
+                
+        //Get the HDCP receiver's V' value (20 bytes in size)
+        if(!hdcp_get_receiver_data((uint8_t*)repeater_prime_v, KSV_SIZE*4, RX_TYPE_REPEATER_PRIME_V))
+        {
+            ret = STATUS_UNSUCCESSFUL;
+            break;
+        }
+
+        
+        if(!hdcp_compare_v_prime(repeater_prime_v, KSV_SIZE))
+        {
+            //set hdcp encryption level to 0
+            hdcp_update_repeater_state(0);
+            hdcp_enable(0);
+            ret = STATUS_UNSUCCESSFUL;
+        }
+        else
+        {
+            ret = STATUS_SUCCESS;
+        }
+    }
+
+    if(ksv_list)
+    {
+            kfree(ksv_list);             
+            ksv_list = NULL;
+    }
+
+
+    return ret;
+}
+
+/*
+ * IsHDCPRepeater : Reads the caps register and informs
+ * whether the received is a repeater
+ *
+ */
+static int hdcp_is_repeater(int *is_repeater)
+{
+    int ret = 0;
+    hdcp_rx_bcaps_t b_caps;
+
+    //Init
+    b_caps.value = 0;
+
+    ret = hdcp_get_receiver_data(&b_caps.value, 1, RX_TYPE_BCAPS);
+    if(ret)
+    {
+        *is_repeater = b_caps.is_reapeater;
+    }
+
+    return ret;
+}
+
+/* Get's the current link status */
+static int hdcp_get_link_status(void)
+{
+    struct drm_device *dev = hdmi_priv->dev;
+    int ret = 0;
+    uint32_t rx_ri = 0;
+    mdfld_hdcp_receiver_ri_t receivers_ri;
+    mdfld_hdcp_status_t status;    
+    uint32_t max_count = 0;
+
+    max_count = HDCP_MAX_RI_QUERY_COUNT;
+    while(max_count)
+    {
+        max_count--;
+
+        //Read the Ri' of reciever
+        ret = read_hdcp_port(RX_TYPE_RI_DATA,(uint8_t*)&rx_ri,2);
+        if(!ret)
+            break; // I2C access failed
+
+        //update the HDCP_Ri' register and read the status reg for cofrmation
+        receivers_ri.value = REG_READ(MDFLD_HDCP_RECEIVER_RI_REG);
+        receivers_ri.ri = rx_ri;
+        REG_WRITE(MDFLD_HDCP_RECEIVER_RI_REG, receivers_ri.value);
+        
+        status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+
+        ret = status.cipher_ri_match_status;
+        if(ret)
+        {
+            //Ri and Ri' matches, hence reciver is a authentic one :)
+            break;
+        }
+        else 
+        {
+            //The Ri changes every 128th frame.Hence if the Ri check fails
+            //that means the sink has updated the Ri value and that can happen
+            //every 128th frame. In that case we wait for the next frame count.
+            //Wait should be around 16 ms.
+            while((status.frame_count&HDCP_NEXT_RI_FRAME) == HDCP_NEXT_RI_FRAME)
+            {
+                status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+            }
+        }
+    }
+
+    return ret;
+}
+
+/*
+ *
+ * GetHDCPEncryptionLevel: 
+ *
+ */
+static void hdcp_get_encryption_level(cp_parameters_t* cp)
+{
+
+    if(hdcp_is_enabled())
+    {
+        cp->level = CP_PROTECTION_LEVEL_HDCP_ON;
+    }
+    else
+    {
+        cp->level = CP_PROTECTION_LEVEL_HDCP_OFF;
+    }
+
+    return ;
+}
+
+/*
+ *
+ * GetCPData: Get Content protection Data
+ * based upon the request from CP
+ *
+ */
+uint32_t hdcp_get_cp_data(cp_parameters_t* cp)
+{
+    uint32_t ret = STATUS_SUCCESS;
+    int is_repeater = 0;
+    
+    if((cp->protect_type_mask & CP_PROTECTION_TYPE_HDCP))
+    {
+        //Check whether HDCP is on
+        hdcp_get_encryption_level(cp);
+
+        if (cp->level != CP_PROTECTION_LEVEL_HDCP_OFF)
+        {
+            // see if the link is valid, do it by authenticating
+            if(!hdcp_get_link_status())
+            {
+                // Encryption setting failed; swtich off the encryption 
+                cp->level = CP_PROTECTION_LEVEL_HDCP_OFF;
+                hdcp_set_encryption_level(cp);
+                ret = STATUS_UNSUCCESSFUL;
+            }
+        }
+        //else
+        //{
+        //HDCP is off
+        //}
+#if 0 //Don't need this for client
+        //Get the BKSv and repeater status. This has to be returned irrespective of
+        //HDCP is ON or Not
+        if(!hdcp_get_receiver_data((uint8_t*)(cp->hdcp.bksv.ab_ksv), CP_HDCP_KEY_SELECTION_VECTOR_SIZE, RX_TYPE_BKSV_DATA))
+        {
+            cp->hdcp.is_repeater = 0;
+            memset(&(cp->hdcp.bksv), 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+            ret = STATUS_DATA_ERROR;
+        }
+        else 
+        {
+            // This is via opregion. This will return all zeros in production mode
+            // Get the AKSV
+            if(hdcp_get_aksv(&aksv))
+            {
+                memcpy(cp->hdcp.aksv.ab_ksv, aksv.uc_aksv, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+            }
+            else // if failed return all zeros
+            {
+                memset(&cp->hdcp.aksv, 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+            }
+        }
+#endif
+        if(ret != STATUS_DATA_ERROR)
+        {
+            if(hdcp_is_repeater(&is_repeater))
+            {
+                cp->hdcp.is_repeater = is_repeater;
+            }
+            else
+            {
+                cp->hdcp.is_repeater = 0;
+                ret = STATUS_DATA_ERROR;
+            }
+        }
+    }
+#if 0    
+    else if(cp->protect_type_mask == CP_PROTECTION_TYPE_NONE)// report repeater capability+BKSV for this mask
+    {
+        if(!hdcp_get_receiver_data((uint8_t*)(cp->hdcp.bksv.ab_ksv), CP_HDCP_KEY_SELECTION_VECTOR_SIZE, RX_TYPE_BKSV_DATA))
+        {
+            cp->hdcp.is_repeater = 0;
+            memset(&(cp->hdcp.bksv), 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+        }
+        else if(hdcp_is_repeater( &is_repeater))
+        {
+            cp->hdcp.is_repeater = is_repeater;
+        }
+        else
+        {
+            cp->hdcp.is_repeater = 0;
+        }
+      
+        // Get the AKSV
+        if(hdcp_get_aksv(&aksv))
+        {
+            memcpy(cp->hdcp.aksv.ab_ksv, aksv.uc_aksv, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+        }
+        else // if failed return all zeros
+        {
+            memset(&cp->hdcp.aksv, 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+        }
+    }
+#endif     
+    else //Invalid mask
+    {
+        //assert(0);
+
+        cp->hdcp.is_repeater = 0;
+        //memset(&(cp->hdcp.bksv), 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+    }
+
+    //Note this data needs to be sent irrespective of any unsupported mask
+    if(ret == STATUS_SUCCESS)
+    {
+        cp->protect_type_mask |= CP_PROTECTION_TYPE_HDCP;
+    }
+
+    return ret;
+}
+
+/*
+ *
+ * SetCPData: Enables/Disables Content protection
+ * based upon the request from CP
+ *
+ */
+uint32_t hdcp_set_cp_data(cp_parameters_t* cp)
+{
+    uint32_t ret = STATUS_UNSUCCESSFUL;
+    int is_repeater = 0;
+
+    if(cp->protect_type_mask & CP_PROTECTION_TYPE_HDCP)
+    {
+        // Get Receiver's repeater status
+        // Note:- Reporting back Repeater status in SetCP Data.
+        // This is because the analyzer for CTS, acts as repeater only 
+        // when the test is running, so notifying this back to opm in 
+        // SetProtectionLevel.
+        if(hdcp_is_repeater(&is_repeater))
+        {
+            cp->hdcp.is_repeater = is_repeater;
+        }
+
+        // Second step flag is if Repeater support needs to be enabled
+        if(cp->hdcp.perform_second_step)
+        {
+            ret = hdcp_activate_repeater(cp);
+            if((ret != STATUS_SUCCESS) && (ret != STATUS_PENDING))
+            {
+                // Encryption setting failed; switch off the encryption 
+                cp->level = CP_PROTECTION_LEVEL_HDCP_OFF;
+                hdcp_set_encryption_level(cp);
+            }
+        }
+        else
+        {
+            ret = hdcp_set_encryption_level(cp);
+
+            if(ret != STATUS_SUCCESS)
+            {
+                // Encryption setting failed; swtich off the encryption 
+                cp->level = CP_PROTECTION_LEVEL_HDCP_OFF;
+                hdcp_set_encryption_level(cp);
+            }
+        }
+        
+        if(ret == STATUS_SUCCESS)
+        {
+#if 0 //Do need this for client        
+            // read the bksv
+            if(!hdcp_get_receiver_data((uint8_t*)(cp->hdcp.bksv.ab_ksv), CP_HDCP_KEY_SELECTION_VECTOR_SIZE, RX_TYPE_BKSV_DATA))
+            {
+                cp->hdcp.is_repeater = 0;
+                memset(&(cp->hdcp.bksv), 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+            }
+            else
+            {
+                // read aksv
+                if(hdcp_get_aksv(&aksv))
+                {
+                    memcpy(cp->hdcp.aksv.ab_ksv,aksv.uc_aksv, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+                }
+                else // if failed return all zeros
+                {
+                    memset(&cp->hdcp.aksv, 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+                }
+            }
+#endif 
+            cp->protect_type_mask |= CP_PROTECTION_TYPE_HDCP;
+        }
+    }
+    else
+    {
+        // No other calls are handled
+        return STATUS_SUCCESS;
+    }
+
+    return ret;
+}
diff --git a/drivers/staging/mrst/drv/mdfld_msic.c b/drivers/staging/mrst/drv/mdfld_msic.c
new file mode 100644 (file)
index 0000000..40b6053
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Jim Liu <jim.liu@intel.com>
+ */
+
+#include "mdfld_msic.h"
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_intel_hdmi.h"
+#include <asm/intel_scu_ipc.h>
+
+#define SRAM_MSIC_VRINT_ADDR 0xFFFF7FCB
+static u8 __iomem *sram_vreg_addr;
+/*
+ *
+ */
+static struct mid_intel_hdmi_priv *hdmi_priv;
+
+void mdfld_msic_init(struct mid_intel_hdmi_priv *p_hdmi_priv)
+{
+       hdmi_priv = p_hdmi_priv;
+}
+
+/**
+ *  hpd_notify_um
+ */
+void hpd_notify_um (void)
+{
+       struct drm_device *dev = hdmi_priv ? hdmi_priv->dev : NULL;
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct pci_dev *pdev = NULL;
+       struct device *ddev = NULL;
+       struct kobject *kobj = NULL;
+
+       if (dev)
+               PSB_DEBUG_ENTRY("\n");
+
+       dev_priv->hdmi_done_reading_edid = false;
+
+       /*find handle to drm kboject*/
+       if(dev == NULL){
+               DRM_ERROR("%s: dev == NULL. \n", __FUNCTION__);
+               return;
+       }
+       pdev = dev->pdev;
+
+       if(pdev == NULL){
+               DRM_ERROR("%s: pdev == NULL. \n", __FUNCTION__);
+               return;
+       }
+       ddev = &pdev->dev;
+
+       if(ddev == NULL){
+               DRM_ERROR("%s: ddev == NULL. \n", __FUNCTION__);
+               return;
+       }
+       kobj = &ddev->kobj;
+
+       if(kobj == NULL){
+               DRM_ERROR("%s: kobj == NULL. \n", __FUNCTION__);
+               return;
+       }
+
+       if (dev_priv->psb_hotplug_state) {
+               DRM_INFO("%s: HPD interrupt. \n", __FUNCTION__);
+               psb_hotplug_notify_change_um("hpd_hdmi", dev_priv->psb_hotplug_state);
+       } else {
+               DRM_ERROR("%s: Hotplug comm layer isn't initialized! \n", __FUNCTION__);
+       }
+
+       return;
+}
+
+/**
+ *  msic_vreg_handler
+ */
+static irqreturn_t msic_vreg_handler(int irq, void *dev_id)
+{
+       struct drm_device *dev = hdmi_priv ? hdmi_priv->dev : NULL;
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       u8 data = 0;
+
+       /* Need to add lock later.*/
+
+       /* Read VREG interrupt status register */
+       if (sram_vreg_addr)
+               data = readb(sram_vreg_addr);
+       else
+               DRM_ERROR("%s: sram_vreg_addr = %p\n", __FUNCTION__, sram_vreg_addr);
+
+       if (dev)
+               PSB_DEBUG_ENTRY("data = 0x%x.\n", data);
+
+       /* handle HDMI HPD interrupts. */
+       if (data & HDMI_HPD_STATUS) {
+               DRM_INFO("%s: HPD interrupt. data = 0x%x. \n", __FUNCTION__, data);
+       
+               if (dev_priv->xserver_start)
+                       hpd_notify_um();
+       }
+
+       /* handle other msic vreq interrupts when necessary. */
+
+       return IRQ_HANDLED;
+}
+
+/**
+ *  msic_probe
+ */
+static int __devinit msic_probe(struct pci_dev *pdev,
+                       const struct pci_device_id *ent)
+{
+       struct drm_device *dev = hdmi_priv ? hdmi_priv->dev : NULL;
+       int ret = 0;
+
+       if (dev)
+               PSB_DEBUG_ENTRY("\n");
+
+       /* enable msic hdmi device */
+       ret = pci_enable_device(pdev);
+
+       if (!ret) {
+
+               if (pdev->device == MSIC_PCI_DEVICE_ID) {
+                       sram_vreg_addr = ioremap_nocache(SRAM_MSIC_VRINT_ADDR, 0x2);
+                       ret = request_irq(pdev->irq, msic_vreg_handler, IRQF_SHARED, "msic_hdmi_driver",(void *)&hdmi_priv);
+               } else
+                       DRM_ERROR("%s: pciid = 0x%x is not msic_hdmi pciid. \n", __FUNCTION__, pdev->device);
+
+               if (!ret) {
+#if 0 /* #ifdef CONFIG_X86_MRST may still be necessary*/
+                       u8 data = 0;
+
+                       /* clear HDMI HPD */
+                       intel_scu_ipc_ioread8(MSIC_VRINT_STATUS, &data);
+                       intel_scu_ipc_iowrite8(MSIC_VRINT_STATUS, data);
+
+                       /* clear MSIC first level VREG interrupt. */
+                       intel_scu_ipc_ioread8(MSIC_IRQLVL1_STATUS, &data);
+                       data &= VREG_STATUS;
+                       intel_scu_ipc_iowrite8(MSIC_IRQLVL1_STATUS, data);
+
+                       /* enable HDMI HPD */
+                       intel_scu_ipc_ioread8(MSIC_VRINT_MASK, &data);
+                       data &= ~HDMI_HPD_MASK;
+                       intel_scu_ipc_iowrite8(MSIC_VRINT_MASK, data);
+
+                       /* enable MSIC first level VREG interrupt. */
+                       intel_scu_ipc_ioread8(MSIC_IRQLVL1_MASK, &data);
+                       data &= ~VREG_MASK;
+                       intel_scu_ipc_iowrite8(MSIC_IRQLVL1_MASK, data);
+                       /* Enable and handle other msic vreq interrupts when necessary. */
+#endif
+               } else {
+                       pci_dev_put(pdev);
+                       DRM_ERROR("%s: request_irq failed. ret = 0x%x. \n", __FUNCTION__, ret);
+               }
+       }
+
+       return ret;
+}
+
+static struct pci_device_id msic_pci_id_list[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, MSIC_PCI_DEVICE_ID) },
+       { 0 }
+};
+
+/*MODULE_DEVICE_TABLE(pci, msic_pci_id_list);*/
+
+
+/* field for registering driver to PCI device */
+static struct pci_driver msic_pci_driver = {
+       .name = "msic_hdmi_driver",
+       .id_table = msic_pci_id_list,
+       .probe = msic_probe
+};
+
+/**
+ *  msic_regsiter_driver - register the msic hdmi device to PCI system.
+ */
+int msic_regsiter_driver(void)
+{
+       return pci_register_driver(&msic_pci_driver);
+}
+
+/**
+ *  msic_unregsiter_driver - unregister the msic hdmi device from PCI system.
+ */
+int msic_unregister_driver(void)
+{
+       if (!sram_vreg_addr) {
+               iounmap(sram_vreg_addr);
+               sram_vreg_addr = NULL;
+       }
+       pci_unregister_driver(&msic_pci_driver);
+       return 0;
+}
diff --git a/drivers/staging/mrst/drv/mdfld_msic.h b/drivers/staging/mrst/drv/mdfld_msic.h
new file mode 100644 (file)
index 0000000..d2e255e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Jim Liu <jim.liu@intel.com>
+ */
+
+#ifndef MDFLD_MSIC_H
+#define MDFLD_MSIC_H
+
+#include "psb_intel_hdmi.h"
+
+#define MSIC_PCI_DEVICE_ID 0x831
+
+int msic_regsiter_driver(void);
+int msic_unregister_driver(void);
+extern void hpd_notify_um (void);
+void mdfld_msic_init(struct mid_intel_hdmi_priv *p_hdmi_priv);
+
+#endif /* MDFLD_MSIC_H */
diff --git a/drivers/staging/mrst/drv/mdfld_output.c b/drivers/staging/mrst/drv/mdfld_output.c
new file mode 100644 (file)
index 0000000..0ae31f6
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#include <linux/init.h>
+#include "mdfld_output.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+
+#include "displays/tpo_cmd.h"
+#include "displays/tpo_vid.h"
+#include "displays/tmd_vid.h"
+#include "displays/hdmi.h"
+#include "tc35876x-dsi-lvds.h"
+
+enum panel_type get_panel_type(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+
+       return dev_priv->panel_id;
+}
+
+int is_panel_vid_or_cmd(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+
+       int ret = 0;
+       switch(dev_priv->panel_id) {
+       case TMD_VID:
+       case TPO_VID:
+       case TC35876X:
+               ret =  MDFLD_DSI_ENCODER_DPI;
+               break;
+       case TMD_CMD:
+       case TPO_CMD:
+       default:
+               ret =  MDFLD_DSI_ENCODER_DBI;
+               break;
+       }
+       return ret;
+}
+
+void mdfld_output_init(struct drm_device* dev)
+{
+       enum panel_type p_type1, p_type2;
+
+       /* MIPI panel 1 */
+       p_type1 = get_panel_type(dev, 0);
+       init_panel(dev, 0, p_type1);
+
+#ifdef CONFIG_MDFD_DUAL_MIPI
+       /* MIPI panel 2 */
+       p_type2 = get_panel_type(dev, 2);
+       init_panel(dev, 2, p_type2);
+#endif
+
+#ifdef CONFIG_MDFD_HDMI
+       /* HDMI panel */
+       init_panel(dev, 0, HDMI);
+#endif
+}
+
+void init_panel(struct drm_device* dev, int mipi_pipe, enum panel_type p_type)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct panel_funcs * p_cmd_funcs = NULL; 
+       struct panel_funcs * p_vid_funcs = NULL;
+
+       p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+       p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+       
+       switch (p_type) {
+       case TPO_CMD:
+               tpo_cmd_init(dev, p_cmd_funcs);
+               mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+               break;
+       case TPO_VID:
+               tpo_vid_init(dev, p_vid_funcs);
+               mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+               break;
+       case TMD_CMD:
+               /*tmd_cmd_init(dev, p_cmd_funcs);*/
+               mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+               break;
+       case TC35876X:
+               tc35876x_bridge_init();
+               /* fallthrough */
+       case TMD_VID:
+               tmd_vid_init(dev, p_vid_funcs);
+               mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+               break;
+       case TPO:       /*TPO panel supports both cmd & vid interfaces*/
+               tpo_cmd_init(dev, p_cmd_funcs);
+               tpo_vid_init(dev, p_vid_funcs);
+               mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, p_vid_funcs);
+               break;
+       case TMD:
+               break;
+       case HDMI:
+               /*hdmi_init(dev);*/
+               printk(KERN_ALERT "GFX: Initializing HDMI");
+               mdfld_hdmi_init(dev, &dev_priv->mode_dev);
+               /*hdmi_output_init(dev);*/
+               break;
+       default:
+               break;
+       }
+}
+
diff --git a/drivers/staging/mrst/drv/mdfld_output.h b/drivers/staging/mrst/drv/mdfld_output.h
new file mode 100644 (file)
index 0000000..876dfd0
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+
+#ifndef MDFLD_OUTPUT_H
+#define MDFLD_OUTPUT_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+
+#define TPO_PANEL_WIDTH        84
+#define TPO_PANEL_HEIGHT       46
+#define TMD_PANEL_WIDTH        39
+#define TMD_PANEL_HEIGHT       71
+
+struct mdfld_dsi_config;
+
+struct panel_info {
+       u32 width_mm;
+       u32 height_mm;
+
+       /*other infos*/
+};
+
+struct panel_funcs {
+       const struct drm_encoder_funcs* encoder_funcs;
+       const struct drm_encoder_helper_funcs* encoder_helper_funcs;
+       struct drm_display_mode* (*get_config_mode)(struct drm_device*);
+       void (*update_fb)(struct mdfld_dsi_dbi_output*, int);
+       int (*get_panel_info)(struct drm_device *, int, struct panel_info *);
+       int (*reset)(int pipe);
+       void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe);
+};
+
+void mdfld_output_init(struct drm_device* dev);
+
+void init_panel(struct drm_device* dev, int mipi_pipe, enum panel_type p_type);
+enum panel_type get_panel_type(struct drm_device *dev, int pipe);
+int is_panel_vid_or_cmd(struct drm_device *dev);
+
+
+#endif
+
+
diff --git a/drivers/staging/mrst/drv/psb_bl.c b/drivers/staging/mrst/drv/psb_bl.c
new file mode 100644 (file)
index 0000000..d5234a4
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ *  psb backlight using HAL
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Eric Knopp
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include <asm/intel_scu_ipc.h>
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "psb_powermgmt.h"
+#include "mdfld_dsi_dbi.h"
+
+#define MRST_BLC_MAX_PWM_REG_FREQ          0xFFFF
+#define BLC_PWM_PRECISION_FACTOR 100   /* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+#define BRIGHTNESS_MIN_LEVEL 1
+#define BRIGHTNESS_MAX_LEVEL 100
+#define BRIGHTNESS_MASK        0xFF
+#define BLC_POLARITY_NORMAL 0
+#define BLC_POLARITY_INVERSE 1
+#define BLC_ADJUSTMENT_MAX 100
+
+#define PSB_BLC_PWM_PRECISION_FACTOR    10
+#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
+#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
+
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT    (16)
+
+static int psb_brightness;
+static struct backlight_device *psb_backlight_device;
+
+int psb_set_brightness(struct backlight_device *bd)
+{
+       struct drm_device *dev = (struct drm_device *)bl_get_data(psb_backlight_device);
+       struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+       int level = bd->props.brightness;
+
+       DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
+
+       /* Perform value bounds checking */
+       if (level < BRIGHTNESS_MIN_LEVEL)
+               level = BRIGHTNESS_MIN_LEVEL;
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                       OSPM_UHB_ONLY_IF_ON)) {
+               u32 adjusted_level = 0;
+
+               /*
+                * Adjust the backlight level with the percent in
+                * dev_priv->blc_adj2
+                */
+               adjusted_level = level * dev_priv->blc_adj2;
+               adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
+
+#ifndef CONFIG_MDFLD_DSI_DPU
+               if((!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL)) &&
+                       (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
+                       mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL);
+                       PSB_DEBUG_ENTRY("Out of DSR before set brightness to %d.\n",adjusted_level);
+               }
+#endif
+               if (get_panel_type(dev, 0) == TC35876X) {
+                       mdfld_dsi_brightness_control(dev, 0, adjusted_level);
+               } else {
+                       if (dev_priv->dbi_panel_on || dev_priv->dpi_panel_on)
+                               mdfld_dsi_brightness_control(dev, 0,
+                                                       adjusted_level);
+               }
+
+               if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
+                       mdfld_dsi_brightness_control(dev, 2, adjusted_level);
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+
+       /* cache the brightness for later use */
+       psb_brightness = level;
+       return 0;
+}
+
+int psb_get_brightness(struct backlight_device *bd)
+{
+       DRM_DEBUG_DRIVER("brightness = 0x%x \n", psb_brightness);
+
+       /* return locally cached var instead of HW read (due to DPST etc.) */
+       return psb_brightness;
+}
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+static struct backlight_ops psb_ops = {
+       .get_brightness = psb_get_brightness,
+       .update_status  = psb_set_brightness,
+};
+
+static int device_backlight_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = (struct drm_psb_private *)
+               dev->dev_private;
+
+       dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
+       dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
+
+       return 0;
+}
+#endif
+
+int psb_backlight_init(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+       struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+       struct backlight_properties props;
+       uint8_t data = 0;
+       int ret = 0;
+
+       dev_priv->b_pmic_backlight = false;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = BRIGHTNESS_MAX_LEVEL;
+       props.type = BACKLIGHT_PLATFORM;
+       psb_backlight_device = backlight_device_register("psb-bl", NULL, (void *)dev, &psb_ops, &props);
+
+       if (IS_ERR(psb_backlight_device))
+               return PTR_ERR(psb_backlight_device);
+
+       if ((ret = device_backlight_init(dev)) != 0)
+               return ret;
+
+       psb_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL;
+       psb_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL;
+       if (dev_priv->b_pmic_backlight) {
+               intel_scu_ipc_ioread8(0x28, &data);
+               dev_priv->saveBKLTCNT = data;
+               intel_scu_ipc_ioread8(0x29, &data);
+               dev_priv->saveBKLTREQ = data;
+               intel_scu_ipc_ioread8(0x2A, &data);
+               dev_priv->saveBKLTBRTL = data;
+       }
+       backlight_update_status(psb_backlight_device);
+#endif
+       return 0;
+}
+
+void psb_backlight_exit(void)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+       psb_backlight_device->props.brightness = 0;
+       backlight_update_status(psb_backlight_device);
+       backlight_device_unregister(psb_backlight_device);
+#endif
+       return;
+}
+
+struct backlight_device * psb_get_backlight_device(void)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+       return psb_backlight_device;
+#endif
+       return NULL;
+}
diff --git a/drivers/staging/mrst/drv/psb_dpst.c b/drivers/staging/mrst/drv/psb_dpst.c
new file mode 100644 (file)
index 0000000..7499b39
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+
+#include "psb_umevents.h"
+#include "psb_dpst.h"
+/**
+ * inform the kernel of the work to be performed and related function.
+ *
+ */
+static DECLARE_WORK(dpst_dev_change_work, &psb_dpst_dev_change_wq);
+/**
+ * psb_dpst_notify_change_um - notify user mode of hotplug changes
+ *
+ * @name: name of event to notify user mode of change to
+ * @state: dpst state struct to get workqueue from
+ *
+ */
+int psb_dpst_notify_change_um(enum dpst_event_enum event,
+                             struct dpst_state *state)
+{
+       if (state == NULL)
+               return IRQ_HANDLED;
+
+       state->dpst_change_wq_data.dev_name_arry_rw_status
+               [state->dpst_change_wq_data.dev_name_write] =
+               DRM_DPST_READY_TO_READ;
+       state->dpst_change_wq_data.dpst_events
+               [state->dpst_change_wq_data.dev_name_write] =
+               event;
+       if (state->dpst_change_wq_data.dev_name_read_write_wrap_ack == 1)
+               state->dpst_change_wq_data.dev_name_read_write_wrap_ack = 0;
+       state->dpst_change_wq_data.dev_name_write++;
+       if (state->dpst_change_wq_data.dev_name_write ==
+          state->dpst_change_wq_data.dev_name_read) {
+               state->dpst_change_wq_data.dev_name_write--;
+               return IRQ_NONE;
+       }
+       if (state->dpst_change_wq_data.dev_name_write >
+          DRM_DPST_RING_DEPTH_MAX) {
+               state->dpst_change_wq_data.dev_name_write = 0;
+               state->dpst_change_wq_data.dev_name_write_wrap = 1;
+       }
+       state->dpst_change_wq_data.hotplug_dev_list = state->list;
+       queue_work(state->dpst_wq, &(state->dpst_change_wq_data.work));
+       return IRQ_HANDLED;
+}
+/*EXPORT_SYMBOL(psb_dpst_notify_change_um); */
+/**
+ *
+ * psb_dpst_create_and_notify_um - create and notify user mode of new dev
+ *
+ * @name: name to give for new event / device
+ * @state: dpst state instaces to associate event with
+ *
+ */
+struct umevent_obj *psb_dpst_create_and_notify_um(const char *name,
+                                                 struct dpst_state *state)
+{
+       return psb_create_umevent_obj(name, state->list);
+
+}
+/*EXPORT_SYMBOL(psb_dpst_create_and_notify_um); */
+/**
+ * psb_dpst_device_pool_create_and_init - make new hotplug device pool
+ *
+ * @parent_kobj - parent kobject to associate dpst kset with
+ * @state - dpst state instance to associate list with
+ *
+ */
+struct umevent_list *psb_dpst_device_pool_create_and_init(
+                                                 struct kobject *parent_kobj,
+                                                 struct dpst_state *state)
+{
+       struct umevent_list *new_hotplug_dev_list = NULL;
+       new_hotplug_dev_list = psb_umevent_create_list();
+       if (new_hotplug_dev_list)
+               psb_umevent_init(parent_kobj, new_hotplug_dev_list,
+                                "psb_dpst");
+
+       state->dpst_wq = create_singlethread_workqueue("dpst-wq");
+
+       if (!state->dpst_wq)
+               return NULL;
+
+       INIT_WORK(&state->dpst_change_wq_data.work, psb_dpst_dev_change_wq);
+
+       state->dpst_change_wq_data.dev_name_read = 0;
+       state->dpst_change_wq_data.dev_name_write = 0;
+       state->dpst_change_wq_data.dev_name_write_wrap = 0;
+       state->dpst_change_wq_data.dev_name_read_write_wrap_ack = 0;
+
+       memset(&(state->dpst_change_wq_data.dev_name_arry_rw_status[0]),
+              0, sizeof(int)*DRM_DPST_RING_DEPTH);
+
+       return new_hotplug_dev_list;
+}
+/*EXPORT_SYMBOL(psb_dpst_device_pool_create_and_init);  */
+/**
+ * psb_dpst_init - init dpst subsystem
+ * @parent_kobj - parent kobject to associate dpst state with
+ *
+ */
+struct dpst_state *psb_dpst_init(struct kobject *parent_kobj)
+{
+       struct dpst_state *state;
+       struct umevent_obj *working_umevent;
+
+       state = kzalloc(sizeof(struct dpst_state), GFP_KERNEL);
+       state->list = NULL;
+       state->list = psb_dpst_device_pool_create_and_init(
+                                                 parent_kobj,
+                                                 state);
+       working_umevent  =
+               psb_dpst_create_and_notify_um("init",
+                                          state);
+       state->dpst_change_wq_data.dev_umevent_arry
+               [DPST_EVENT_INIT_COMPLETE] = &(working_umevent->head);
+       working_umevent  =
+               psb_dpst_create_and_notify_um("hist_int",
+                                          state);
+       state->dpst_change_wq_data.dev_umevent_arry
+               [DPST_EVENT_HIST_INTERRUPT] = &(working_umevent->head);
+       working_umevent  =
+               psb_dpst_create_and_notify_um("term",
+                                          state);
+       state->dpst_change_wq_data.dev_umevent_arry
+               [DPST_EVENT_TERMINATE] = &(working_umevent->head);
+       working_umevent  =
+               psb_dpst_create_and_notify_um("phase_done",
+                                          state);
+       state->dpst_change_wq_data.dev_umevent_arry
+               [DPST_EVENT_PHASE_COMPLETE] = &(working_umevent->head);
+
+       return state;
+}
+/*EXPORT_SYMBOL(psb_dpst_init); */
+/**
+ * psb_dpst_device_pool_destroy - destroy all dpst related resources
+ *
+ * @state: dpst state instance to destroy
+ *
+ */
+void psb_dpst_device_pool_destroy(struct dpst_state *state)
+{
+       int i;
+       struct umevent_list *list;
+       struct umevent_obj *umevent_test;
+       list = state->list;
+       flush_workqueue(state->dpst_wq);
+       destroy_workqueue(state->dpst_wq);
+       for (i = 0; i < DRM_DPST_MAX_NUM_EVENTS;  i++) {
+               umevent_test = list_entry(
+                         (state->dpst_change_wq_data.dev_umevent_arry[i]),
+                         struct umevent_obj, head);
+               state->dpst_change_wq_data.dev_umevent_arry[i] = NULL;
+       }
+       psb_umevent_cleanup(list);
+       kfree(state);
+}
+/*EXPORT_SYMBOL(psb_dpst_device_pool_destroy); */
+/**
+ * psb_dpst_dev_change_wq - change workqueue implementation
+ *
+ * @work: work struct to use for kernel scheduling
+ *
+ */
+void psb_dpst_dev_change_wq(struct work_struct *work)
+{
+       struct dpst_disp_workqueue_data *wq_data;
+       int curr_event_index;
+       wq_data = to_dpst_disp_workqueue_data(work);
+       if (wq_data->dev_name_write_wrap == 1) {
+               wq_data->dev_name_read_write_wrap_ack = 1;
+               wq_data->dev_name_write_wrap = 0;
+               while (wq_data->dev_name_read != DRM_DPST_RING_DEPTH_MAX) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_DPST_READY_TO_READ) {
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                               DRM_DPST_READ_COMPLETE;
+                               curr_event_index = wq_data->dpst_events
+                                       [wq_data->dev_name_read];
+                               psb_umevent_notify_change_gfxsock
+                                       (list_entry(
+                                          (wq_data->dev_umevent_arry
+                                           [curr_event_index]),
+                                          struct umevent_obj, head),
+                                        DRM_DPST_SOCKET_GROUP_ID);
+                       }
+                       wq_data->dev_name_read++;
+               }
+               wq_data->dev_name_read = 0;
+               while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_DPST_READY_TO_READ) {
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                               DRM_DPST_READ_COMPLETE;
+                               curr_event_index = wq_data->dpst_events
+                                       [wq_data->dev_name_read];
+                               psb_umevent_notify_change_gfxsock
+                                       (list_entry(
+                                          (wq_data->dev_umevent_arry
+                                           [curr_event_index]),
+                                          struct umevent_obj, head),
+                                        DRM_DPST_SOCKET_GROUP_ID);
+                       }
+                       wq_data->dev_name_read++;
+               }
+       } else {
+               while (wq_data->dev_name_read < wq_data->dev_name_write) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_DPST_READY_TO_READ) {
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                                       DRM_DPST_READ_COMPLETE;
+                               curr_event_index = wq_data->dpst_events
+                                       [wq_data->dev_name_read];
+                               psb_umevent_notify_change_gfxsock
+                                       (list_entry(
+                                          (wq_data->dev_umevent_arry
+                                           [curr_event_index]),
+                                          struct umevent_obj, head),
+                                        DRM_DPST_SOCKET_GROUP_ID);
+                       }
+                       wq_data->dev_name_read++;
+               }
+       }
+       if (wq_data->dev_name_read > DRM_DPST_RING_DEPTH_MAX)
+               wq_data->dev_name_read = 0;
+}
+/*EXPORT_SYMBOL(psb_dpst_dev_change_wq); */
diff --git a/drivers/staging/mrst/drv/psb_dpst.h b/drivers/staging/mrst/drv/psb_dpst.h
new file mode 100644 (file)
index 0000000..6f24a05
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+
+#ifndef _PSB_DPST_H_
+#define _PSB_DPST_H_
+/**
+ * required includes
+ *
+ */
+#include "psb_umevents.h"
+/**
+ * dpst event enumeration
+ *
+ */
+enum dpst_event_enum {
+       DPST_EVENT_INIT_COMPLETE,
+       DPST_EVENT_HIST_INTERRUPT,
+       DPST_EVENT_TERMINATE,
+       DPST_EVENT_PHASE_COMPLETE,
+       DPST_MAX_EVENT
+};
+/**
+ * dpst specific defines
+ *
+ */
+#define DRM_DPST_RING_DEPTH 256
+#define DRM_DPST_RING_DEPTH_MAX (DRM_DPST_RING_DEPTH-1)
+#define DRM_DPST_READY_TO_READ 1
+#define DRM_DPST_READ_COMPLETE 2
+#define DRM_DPST_MAX_NUM_EVENTS (DPST_MAX_EVENT)
+/**
+ * dpst workqueue data struct.
+ */
+struct dpst_disp_workqueue_data {
+       struct work_struct work;
+       const char *dev_name;
+       int dev_name_write;
+       int dev_name_read;
+       int dev_name_write_wrap;
+       int dev_name_read_write_wrap_ack;
+       enum dpst_event_enum dpst_events[DRM_DPST_RING_DEPTH];
+       int dev_name_arry_rw_status[DRM_DPST_RING_DEPTH];
+       struct umevent_list *hotplug_dev_list;
+       struct list_head *dev_umevent_arry[DRM_DPST_MAX_NUM_EVENTS];
+};
+/**
+ * dpst state structure
+ *
+ */
+struct dpst_state {
+       struct workqueue_struct *dpst_wq;
+       struct dpst_disp_workqueue_data dpst_change_wq_data;
+       struct umevent_list *list;
+};
+/**
+ * main interface function prototytpes for dpst support.
+ *
+ */
+extern struct dpst_state *psb_dpst_init(struct kobject *parent_kobj);
+extern int psb_dpst_notify_change_um(enum dpst_event_enum event,
+                                    struct dpst_state *state);
+extern struct umevent_obj *psb_dpst_create_and_notify_um(const char *name,
+                                                struct dpst_state *state);
+extern struct umevent_list *psb_dpst_device_pool_create_and_init(
+                                                struct kobject *parent_kobj,
+                                                struct dpst_state *state);
+extern void psb_dpst_device_pool_destroy(struct dpst_state *state);
+/**
+ * to go back and forth between work struct and workqueue data
+ *
+ */
+#define to_dpst_disp_workqueue_data(x) \
+       container_of(x, struct dpst_disp_workqueue_data, work)
+
+/**
+ * function prototypes for workqueue implementation
+ *
+ */
+extern void psb_dpst_dev_change_wq(struct work_struct *work);
+#endif
diff --git a/drivers/staging/mrst/drv/psb_drm.h b/drivers/staging/mrst/drv/psb_drm.h
new file mode 100644 (file)
index 0000000..2400858
--- /dev/null
@@ -0,0 +1,708 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRM_H_
+#define _PSB_DRM_H_
+
+#if defined(__linux__) && !defined(__KERNEL__)
+#include<stdint.h>
+#include <linux/types.h>
+#include "drm_mode.h"
+#endif
+
+#include "psb_ttm_fence_user.h"
+#include "psb_ttm_placement_user.h"
+
+/*
+ * Menlow/MRST graphics driver package version
+ * a.b.c.xxxx
+ * a - Product Family: 5 - Linux
+ * b - Major Release Version: 0 - non-Gallium (Unbuntu);
+ *                            1 - Gallium (Moblin2)
+ * c - Hotfix Release
+ * xxxx - Graphics internal build #
+ */
+#define PSB_PACKAGE_VERSION "5.3.0.32L.0047"
+
+#define DRM_PSB_SAREA_MAJOR 0
+#define DRM_PSB_SAREA_MINOR 2
+#define PSB_FIXED_SHIFT 16
+
+#define PSB_NUM_PIPE 3
+
+/*
+ * Public memory types.
+ */
+
+#define DRM_PSB_MEM_MMU TTM_PL_PRIV1
+#define DRM_PSB_FLAG_MEM_MMU TTM_PL_FLAG_PRIV1
+
+#define TTM_PL_CI               TTM_PL_PRIV0
+#define TTM_PL_FLAG_CI          TTM_PL_FLAG_PRIV0       
+
+#define TTM_PL_RAR               TTM_PL_PRIV2
+#define TTM_PL_FLAG_RAR          TTM_PL_FLAG_PRIV2       
+
+typedef int32_t psb_fixed;
+typedef uint32_t psb_ufixed;
+
+static inline int32_t psb_int_to_fixed(int a)
+{
+       return a * (1 << PSB_FIXED_SHIFT);
+}
+
+static inline uint32_t psb_unsigned_to_ufixed(unsigned int a)
+{
+       return a << PSB_FIXED_SHIFT;
+}
+
+/*Status of the command sent to the gfx device.*/
+typedef enum {
+       DRM_CMD_SUCCESS,
+       DRM_CMD_FAILED,
+       DRM_CMD_HANG
+} drm_cmd_status_t;
+
+struct drm_psb_scanout {
+       uint32_t buffer_id;     /* DRM buffer object ID */
+       uint32_t rotation;      /* Rotation as in RR_rotation definitions */
+       uint32_t stride;        /* Buffer stride in bytes */
+       uint32_t depth;         /* Buffer depth in bits (NOT) bpp */
+       uint32_t width;         /* Buffer width in pixels */
+       uint32_t height;        /* Buffer height in lines */
+       int32_t transform[3][3];        /* Buffer composite transform */
+       /* (scaling, rot, reflect) */
+};
+
+#define DRM_PSB_SAREA_OWNERS 16
+#define DRM_PSB_SAREA_OWNER_2D 0
+#define DRM_PSB_SAREA_OWNER_3D 1
+
+#define DRM_PSB_SAREA_SCANOUTS 3
+
+struct drm_psb_sarea {
+       /* Track changes of this data structure */
+
+       uint32_t major;
+       uint32_t minor;
+
+       /* Last context to touch part of hw */
+       uint32_t ctx_owners[DRM_PSB_SAREA_OWNERS];
+
+       /* Definition of front- and rotated buffers */
+       uint32_t num_scanouts;
+       struct drm_psb_scanout scanouts[DRM_PSB_SAREA_SCANOUTS];
+
+       int planeA_x;
+       int planeA_y;
+       int planeA_w;
+       int planeA_h;
+       int planeB_x;
+       int planeB_y;
+       int planeB_w;
+       int planeB_h;
+       /* Number of active scanouts */
+       uint32_t num_active_scanouts;
+};
+
+#define PSB_RELOC_MAGIC         0x67676767
+#define PSB_RELOC_SHIFT_MASK    0x0000FFFF
+#define PSB_RELOC_SHIFT_SHIFT   0
+#define PSB_RELOC_ALSHIFT_MASK  0xFFFF0000
+#define PSB_RELOC_ALSHIFT_SHIFT 16
+
+#define PSB_RELOC_OP_OFFSET     0      /* Offset of the indicated
+                                        * buffer
+                                        */
+
+struct drm_psb_reloc {
+       uint32_t reloc_op;
+       uint32_t where;         /* offset in destination buffer */
+       uint32_t buffer;        /* Buffer reloc applies to */
+       uint32_t mask;          /* Destination format: */
+       uint32_t shift;         /* Destination format: */
+       uint32_t pre_add;       /* Destination format: */
+       uint32_t background;    /* Destination add */
+       uint32_t dst_buffer;    /* Destination buffer. Index into buffer_list */
+       uint32_t arg0;          /* Reloc-op dependant */
+       uint32_t arg1;
+};
+
+
+#define PSB_GPU_ACCESS_READ         (1ULL << 32)
+#define PSB_GPU_ACCESS_WRITE        (1ULL << 33)
+#define PSB_GPU_ACCESS_MASK         (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)
+
+#define PSB_BO_FLAG_COMMAND         (1ULL << 52)
+
+#define PSB_ENGINE_2D 0
+#define PSB_ENGINE_VIDEO 1
+#define LNC_ENGINE_ENCODE 5
+
+/*
+ * For this fence class we have a couple of
+ * fence types.
+ */
+
+#define _PSB_FENCE_EXE_SHIFT           0
+#define _PSB_FENCE_FEEDBACK_SHIFT      4
+
+#define _PSB_FENCE_TYPE_EXE         (1 << _PSB_FENCE_EXE_SHIFT)
+#define _PSB_FENCE_TYPE_FEEDBACK    (1 << _PSB_FENCE_FEEDBACK_SHIFT)
+
+#define PSB_NUM_ENGINES 6
+
+
+#define PSB_FEEDBACK_OP_VISTEST (1 << 0)
+
+struct drm_psb_extension_rep {
+       int32_t exists;
+       uint32_t driver_ioctl_offset;
+       uint32_t sarea_offset;
+       uint32_t major;
+       uint32_t minor;
+       uint32_t pl;
+};
+
+#define DRM_PSB_EXT_NAME_LEN 128
+
+union drm_psb_extension_arg {
+       char extension[DRM_PSB_EXT_NAME_LEN];
+       struct drm_psb_extension_rep rep;
+};
+
+struct psb_validate_req {
+       uint64_t set_flags;
+       uint64_t clear_flags;
+       uint64_t next;
+       uint64_t presumed_gpu_offset;
+       uint32_t buffer_handle;
+       uint32_t presumed_flags;
+       uint32_t group;
+       uint32_t pad64;
+};
+
+struct psb_validate_rep {
+       uint64_t gpu_offset;
+       uint32_t placement;
+       uint32_t fence_type_mask;
+};
+
+#define PSB_USE_PRESUMED     (1 << 0)
+
+struct psb_validate_arg {
+       int handled;
+       int ret;
+       union {
+               struct psb_validate_req req;
+               struct psb_validate_rep rep;
+       } d;
+};
+
+
+#define DRM_PSB_FENCE_NO_USER        (1 << 0)
+
+struct psb_ttm_fence_rep {
+       uint32_t handle;
+       uint32_t fence_class;
+       uint32_t fence_type;
+       uint32_t signaled_types;
+       uint32_t error;
+};
+
+typedef struct drm_psb_cmdbuf_arg {
+       uint64_t buffer_list;   /* List of buffers to validate */
+       uint64_t clip_rects;    /* See i915 counterpart */
+       uint64_t scene_arg;
+       uint64_t fence_arg;
+
+       uint32_t ta_flags;
+
+       uint32_t ta_handle;     /* TA reg-value pairs */
+       uint32_t ta_offset;
+       uint32_t ta_size;
+
+       uint32_t oom_handle;
+       uint32_t oom_offset;
+       uint32_t oom_size;
+
+       uint32_t cmdbuf_handle; /* 2D Command buffer object or, */
+       uint32_t cmdbuf_offset; /* rasterizer reg-value pairs */
+       uint32_t cmdbuf_size;
+
+       uint32_t reloc_handle;  /* Reloc buffer object */
+       uint32_t reloc_offset;
+       uint32_t num_relocs;
+
+       int32_t damage;         /* Damage front buffer with cliprects */
+       /* Not implemented yet */
+       uint32_t fence_flags;
+       uint32_t engine;
+
+       /*
+        * Feedback;
+        */
+
+       uint32_t feedback_ops;
+       uint32_t feedback_handle;
+       uint32_t feedback_offset;
+       uint32_t feedback_breakpoints;
+       uint32_t feedback_size;
+} drm_psb_cmdbuf_arg_t;
+
+typedef struct drm_psb_pageflip_arg {
+       uint32_t flip_offset;
+       uint32_t stride;
+} drm_psb_pageflip_arg_t;
+
+typedef enum {
+       LNC_VIDEO_DEVICE_INFO,
+       LNC_VIDEO_GETPARAM_RAR_INFO,
+       LNC_VIDEO_GETPARAM_CI_INFO,
+       LNC_VIDEO_GETPARAM_RAR_HANDLER_OFFSET,
+       LNC_VIDEO_FRAME_SKIP,
+       IMG_VIDEO_DECODE_STATUS,
+       IMG_VIDEO_NEW_CONTEXT,
+       IMG_VIDEO_RM_CONTEXT,
+       IMG_VIDEO_MB_ERROR
+} lnc_getparam_key_t;
+
+struct drm_lnc_video_getparam_arg {
+       lnc_getparam_key_t key;
+       uint64_t arg;   /* argument pointer */
+       uint64_t value; /* feed back pointer */
+};
+
+
+/*
+ * Feedback components:
+ */
+
+/*
+ * Vistest component. The number of these in the feedback buffer
+ * equals the number of vistest breakpoints + 1.
+ * This is currently the only feedback component.
+ */
+
+struct drm_psb_vistest {
+       uint32_t vt[8];
+};
+
+struct drm_psb_sizes_arg {
+       uint32_t ta_mem_size;
+       uint32_t mmu_size;
+       uint32_t pds_size;
+       uint32_t rastgeom_size;
+       uint32_t tt_size;
+       uint32_t vram_size;
+};
+
+struct drm_psb_hist_status_arg {
+       uint32_t buf[32];
+};
+
+struct drm_psb_dpst_lut_arg {
+       uint8_t lut[256];
+       int output_id;
+};
+
+struct mrst_timing_info {
+       uint16_t pixel_clock;
+       uint8_t hactive_lo;
+       uint8_t hblank_lo;
+       uint8_t hblank_hi:4;
+       uint8_t hactive_hi:4;
+       uint8_t vactive_lo;
+       uint8_t vblank_lo;
+       uint8_t vblank_hi:4;
+       uint8_t vactive_hi:4;
+       uint8_t hsync_offset_lo;
+       uint8_t hsync_pulse_width_lo;
+       uint8_t vsync_pulse_width_lo:4;
+       uint8_t vsync_offset_lo:4;
+       uint8_t vsync_pulse_width_hi:2;
+       uint8_t vsync_offset_hi:2;
+       uint8_t hsync_pulse_width_hi:2;
+       uint8_t hsync_offset_hi:2;
+       uint8_t width_mm_lo;
+       uint8_t height_mm_lo;
+       uint8_t height_mm_hi:4;
+       uint8_t width_mm_hi:4;
+       uint8_t hborder;
+       uint8_t vborder;
+       uint8_t unknown0:1;
+       uint8_t hsync_positive:1;
+       uint8_t vsync_positive:1;
+       uint8_t separate_sync:2;
+       uint8_t stereo:1;
+       uint8_t unknown6:1;
+       uint8_t interlaced:1;
+} __attribute__((packed));
+
+struct gct_r10_timing_info {
+       uint16_t pixel_clock;
+       uint32_t hactive_lo:8;
+       uint32_t hactive_hi:4;
+       uint32_t hblank_lo:8;
+       uint32_t hblank_hi:4;
+       uint32_t hsync_offset_lo:8;
+       uint16_t hsync_offset_hi:2;
+       uint16_t hsync_pulse_width_lo:8;
+       uint16_t hsync_pulse_width_hi:2;
+       uint16_t hsync_positive:1;
+       uint16_t rsvd_1:3;
+       uint8_t  vactive_lo:8;
+       uint16_t vactive_hi:4;
+       uint16_t vblank_lo:8;
+       uint16_t vblank_hi:4;
+       uint16_t vsync_offset_lo:4;
+       uint16_t vsync_offset_hi:2;
+       uint16_t vsync_pulse_width_lo:4;
+       uint16_t vsync_pulse_width_hi:2;
+       uint16_t vsync_positive:1;
+       uint16_t rsvd_2:3;
+} __attribute__((packed));
+
+struct mrst_panel_descriptor_v1{
+       uint32_t Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
+                               /* 0x61190 if MIPI */
+       uint32_t Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/
+       uint32_t Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/
+       uint32_t Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */
+                                               /* Register 0x61210 */
+       struct mrst_timing_info DTD;/*18 bytes, Standard definition */
+       uint16_t Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */
+                               /* Bit 0, Frequency, 15 bits,0 - 32767Hz */
+                       /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */
+       uint16_t Panel_MIPI_Display_Descriptor;
+                       /*16 bits, Defined as follows: */
+                       /* if MIPI, 0x0000 if LVDS */
+                       /* Bit 0, Type, 2 bits, */
+                       /* 0: Type-1, */
+                       /* 1: Type-2, */
+                       /* 2: Type-3, */
+                       /* 3: Type-4 */
+                       /* Bit 2, Pixel Format, 4 bits */
+                       /* Bit0: 16bpp (not supported in LNC), */
+                       /* Bit1: 18bpp loosely packed, */
+                       /* Bit2: 18bpp packed, */
+                       /* Bit3: 24bpp */
+                       /* Bit 6, Reserved, 2 bits, 00b */
+               /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
+                       /* Bit 14, Reserved, 2 bits, 00b */
+} __attribute__ ((packed));
+
+struct mrst_panel_descriptor_v2{
+       uint32_t Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
+                               /* 0x61190 if MIPI */
+       uint32_t Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/
+       uint32_t Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/
+       uint8_t Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */
+                                               /* Register 0x61210 */
+       struct mrst_timing_info DTD;/*18 bytes, Standard definition */
+       uint16_t Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/
+                               /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/
+       uint8_t Panel_Initial_Brightness;/* [7:0] 0 - 100% */
+                       /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/
+       uint16_t Panel_MIPI_Display_Descriptor;
+                       /*16 bits, Defined as follows: */
+                       /* if MIPI, 0x0000 if LVDS */
+                       /* Bit 0, Type, 2 bits, */
+                       /* 0: Type-1, */
+                       /* 1: Type-2, */
+                       /* 2: Type-3, */
+                       /* 3: Type-4 */
+                       /* Bit 2, Pixel Format, 4 bits */
+                       /* Bit0: 16bpp (not supported in LNC), */
+                       /* Bit1: 18bpp loosely packed, */
+                       /* Bit2: 18bpp packed, */
+                       /* Bit3: 24bpp */
+                       /* Bit 6, Reserved, 2 bits, 00b */
+               /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
+                       /* Bit 14, Reserved, 2 bits, 00b */
+} __attribute__ ((packed));
+
+union mrst_panel_rx{
+       struct{
+               uint16_t NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/
+                       /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */
+               uint16_t MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */
+               /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/
+               uint16_t SupportedVideoTransferMode:2; /*0: Non-burst only */
+                                       /* 1: Burst and non-burst */
+                                       /* 2/3: Reserved */
+               uint16_t HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/
+               uint16_t DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/
+               uint16_t ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/
+               uint16_t BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */
+               uint16_t Rsvd:5;/*5 bits,00000b */
+       } panelrx;
+       uint16_t panel_receiver;
+} __attribute__ ((packed));
+
+struct gct_ioctl_arg{
+       uint8_t bpi; /* boot panel index, number of panel used during boot */
+       uint8_t pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */
+       struct mrst_timing_info DTD; /* timing info for the selected panel */
+       uint32_t Panel_Port_Control;
+       uint32_t PP_On_Sequencing;/*1 dword,Register 0x61208,*/
+       uint32_t PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/
+       uint32_t PP_Cycle_Delay;
+       uint16_t Panel_Backlight_Inverter_Descriptor;
+       uint16_t Panel_MIPI_Display_Descriptor;
+} __attribute__ ((packed));
+
+struct mrst_vbt{
+       char Signature[4]; /*4 bytes,"$GCT" */
+       uint8_t Revision; /*1 byte */
+       uint8_t Size; /*1 byte */
+       uint8_t Checksum; /*1 byte,Calculated*/
+       void *mrst_gct;
+} __attribute__ ((packed));
+
+struct mrst_gct_v1{ /* expect this table to change per customer request*/
+       union{ /*8 bits,Defined as follows: */
+               struct{
+                       uint8_t PanelType:4; /*4 bits, Bit field for panels*/
+                                       /* 0 - 3: 0 = LVDS, 1 = MIPI*/
+                                       /*2 bits,Specifies which of the*/
+                       uint8_t BootPanelIndex:2;
+                                       /* 4 panels to use by default*/
+                       uint8_t BootMIPI_DSI_RxIndex:2;/*Specifies which of*/
+                                       /* the 4 MIPI DSI receivers to use*/
+                       } PD;
+               uint8_t PanelDescriptor;
+       };
+       struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/
+       union mrst_panel_rx panelrx[4]; /* panel receivers*/
+} __attribute__ ((packed));
+
+struct mrst_gct_v2{ /* expect this table to change per customer request*/
+       union{ /*8 bits,Defined as follows: */
+               struct{
+                       uint8_t PanelType:4; /*4 bits, Bit field for panels*/
+                                       /* 0 - 3: 0 = LVDS, 1 = MIPI*/
+                                       /*2 bits,Specifies which of the*/
+                       uint8_t BootPanelIndex:2;
+                                       /* 4 panels to use by default*/
+                       uint8_t BootMIPI_DSI_RxIndex:2;/*Specifies which of*/
+                                       /* the 4 MIPI DSI receivers to use*/
+                       } PD;
+               uint8_t PanelDescriptor;
+       };
+       struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/
+       union mrst_panel_rx panelrx[4]; /* panel receivers*/
+} __attribute__ ((packed));
+
+#define PSB_DC_CRTC_SAVE 0x01
+#define PSB_DC_CRTC_RESTORE 0x02
+#define PSB_DC_OUTPUT_SAVE 0x04
+#define PSB_DC_OUTPUT_RESTORE 0x08
+#define PSB_DC_CRTC_MASK 0x03
+#define PSB_DC_OUTPUT_MASK 0x0C
+
+struct drm_psb_dc_state_arg {
+       uint32_t flags;
+       uint32_t obj_id;
+};
+
+struct drm_psb_mode_operation_arg {
+       uint32_t obj_id;
+       uint16_t operation;
+       struct drm_mode_modeinfo mode;
+       void *data;
+};
+
+struct drm_psb_stolen_memory_arg {
+       uint32_t base;
+       uint32_t size;
+};
+
+/*Display Register Bits*/
+#define REGRWBITS_PFIT_CONTROLS                        (1 << 0)
+#define REGRWBITS_PFIT_AUTOSCALE_RATIOS                (1 << 1)
+#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS (1 << 2)
+#define REGRWBITS_PIPEASRC                     (1 << 3)
+#define REGRWBITS_PIPEBSRC                     (1 << 4)
+#define REGRWBITS_VTOTAL_A                     (1 << 5)
+#define REGRWBITS_VTOTAL_B                     (1 << 6)
+#define REGRWBITS_DSPACNTR     (1 << 8)
+#define REGRWBITS_DSPBCNTR     (1 << 9)
+#define REGRWBITS_DSPCCNTR     (1 << 10)
+
+/*Overlay Register Bits*/
+#define OV_REGRWBITS_OVADD                     (1 << 0)
+#define OV_REGRWBITS_OGAM_ALL                  (1 << 1)
+
+#define OVC_REGRWBITS_OVADD                  (1 << 2)
+#define OVC_REGRWBITS_OGAM_ALL                 (1 << 3)
+
+struct drm_psb_register_rw_arg {
+       uint32_t b_force_hw_on;
+
+       uint32_t display_read_mask;
+       uint32_t display_write_mask;
+
+       struct {
+               uint32_t pfit_controls;
+               uint32_t pfit_autoscale_ratios;
+               uint32_t pfit_programmed_scale_ratios;
+               uint32_t pipeasrc;
+               uint32_t pipebsrc;
+               uint32_t vtotal_a;
+               uint32_t vtotal_b;
+               uint32_t dspcntr_a;
+               uint32_t dspcntr_b;
+       } display;
+
+       uint32_t overlay_read_mask;
+       uint32_t overlay_write_mask;
+
+       struct {
+               uint32_t OVADD;
+               uint32_t OGAMC0;
+               uint32_t OGAMC1;
+               uint32_t OGAMC2;
+               uint32_t OGAMC3;
+               uint32_t OGAMC4;
+               uint32_t OGAMC5;
+               uint32_t IEP_ENABLED;
+               uint32_t IEP_BLE_MINMAX;
+               uint32_t IEP_BSSCC_CONTROL;
+                uint32_t b_wait_vblank;
+       } overlay;
+
+       uint32_t sprite_enable_mask;
+       uint32_t sprite_disable_mask;
+
+       struct {
+               uint32_t dspa_control;
+               uint32_t dspa_key_value;
+               uint32_t dspa_key_mask;
+               uint32_t dspc_control;
+               uint32_t dspc_stride;
+               uint32_t dspc_position;
+               uint32_t dspc_linear_offset;
+               uint32_t dspc_size;
+               uint32_t dspc_surface;
+       } sprite;
+
+       uint32_t subpicture_enable_mask;
+       uint32_t subpicture_disable_mask;
+};
+
+struct psb_gtt_mapping_arg {
+       void *hKernelMemInfo;
+       uint32_t offset_pages;
+};
+
+struct drm_psb_getpageaddrs_arg {
+       uint32_t handle;
+       unsigned long *page_addrs;
+       unsigned long gtt_offset;
+};
+
+
+#define MAX_SLICES_PER_PICTURE 72
+typedef struct drm_psb_msvdx_decode_status {
+       uint32_t fw_status;
+       uint32_t num_error_slice;
+       int32_t start_error_mb_list[MAX_SLICES_PER_PICTURE];
+       int32_t end_error_mb_list[MAX_SLICES_PER_PICTURE];
+       int32_t slice_missing_or_error[MAX_SLICES_PER_PICTURE];
+} drm_psb_msvdx_decode_status_t;
+
+/* Controlling the kernel modesetting buffers */
+
+#define DRM_PSB_KMS_OFF                0x00
+#define DRM_PSB_KMS_ON         0x01
+#define DRM_PSB_VT_LEAVE        0x02
+#define DRM_PSB_VT_ENTER        0x03
+#define DRM_PSB_EXTENSION       0x06
+#define DRM_PSB_SIZES           0x07
+#define DRM_PSB_FUSE_REG       0x08
+#define DRM_PSB_VBT            0x09
+#define DRM_PSB_DC_STATE       0x0A
+#define DRM_PSB_ADB            0x0B
+#define DRM_PSB_MODE_OPERATION 0x0C
+#define DRM_PSB_STOLEN_MEMORY  0x0D
+#define DRM_PSB_REGISTER_RW    0x0E
+#define DRM_PSB_GTT_MAP         0x0F
+#define DRM_PSB_GTT_UNMAP       0x10
+#define DRM_PSB_GETPAGEADDRS   0x11
+/**
+ * NOTE: Add new commands here, but increment
+ * the values below and increment their
+ * corresponding defines where they're
+ * defined elsewhere.
+ */
+#define DRM_PVR_RESERVED1      0x12
+#define DRM_PVR_RESERVED2      0x13
+#define DRM_PVR_RESERVED3      0x14
+#define DRM_PVR_RESERVED4      0x15
+#define DRM_PVR_RESERVED5      0x16
+
+#define DRM_PSB_HIST_ENABLE    0x17
+#define DRM_PSB_HIST_STATUS    0x18
+#define DRM_PSB_UPDATE_GUARD   0x19
+#define DRM_PSB_INIT_COMM      0x1A
+#define DRM_PSB_DPST           0x1B
+#define DRM_PSB_GAMMA          0x1C
+#define DRM_PSB_DPST_BL                0x1D
+
+#define DRM_PVR_RESERVED6      0x1E
+
+#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
+#define DRM_PSB_DPU_QUERY 0x20
+#define DRM_PSB_DPU_DSR_ON 0x21
+#define DRM_PSB_DPU_DSR_OFF 0x22
+
+#define DRM_PSB_DSR_ENABLE     0xfffffffe
+#define DRM_PSB_DSR_DISABLE    0xffffffff
+
+struct psb_drm_dpu_rect {  
+    int x, y;             
+    int width, height;    
+};  
+
+struct drm_psb_drv_dsr_off_arg {
+       int screen;
+       struct psb_drm_dpu_rect damage_rect;
+};
+
+
+struct drm_psb_dev_info_arg {
+       uint32_t num_use_attribute_registers;
+};
+#define DRM_PSB_DEVINFO         0x01
+
+#define PSB_MODE_OPERATION_MODE_VALID  0x01
+#define PSB_MODE_OPERATION_SET_DC_BASE  0x02
+
+struct drm_psb_get_pipe_from_crtc_id_arg {
+       /** ID of CRTC being requested **/
+       uint32_t crtc_id;
+
+       /** pipe of requested CRTC **/
+       uint32_t pipe;
+};
+
+#endif
diff --git a/drivers/staging/mrst/drv/psb_drv.c b/drivers/staging/mrst/drv/psb_drv.c
new file mode 100644 (file)
index 0000000..8f00279
--- /dev/null
@@ -0,0 +1,2853 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_fb.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include <drm/drm_pciids.h>
+#include "pvr_drm_shared.h"
+#include "psb_powermgmt.h"
+#include "img_types.h"
+#include <linux/cpu.h>
+#include <linux/dmi.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+
+#include "mdfld_dsi_dbi.h"
+#ifdef CONFIG_MDFLD_DSI_DPU
+#include "mdfld_dsi_dbi_dpu.h"
+#endif
+
+#ifdef CONFIG_MDFD_GL3
+#include "mdfld_gl3.h"
+#endif
+
+#ifdef CONFIG_MDFD_HDMI
+#include "mdfld_msic.h"
+#endif
+#include "psb_intel_hdmi.h"
+
+/*IMG headers*/
+#include "pvr_drm_shared.h"
+#include "img_types.h"
+#include "pvr_bridge.h"
+#include "linkage.h"
+
+#include "bufferclass_video_linux.h"
+
+int drm_psb_debug;
+/*EXPORT_SYMBOL(drm_psb_debug); */
+static int drm_psb_trap_pagefaults;
+
+int drm_psb_disable_vsync = 1;
+int drm_psb_no_fb;
+int drm_psb_force_pipeb;
+int drm_msvdx_pmpolicy = PSB_PMPOLICY_POWERDOWN;
+int drm_psb_cpurelax = 0;
+int drm_psb_udelaydivider = 1;
+int drm_psb_udelaymultiplier = 1;
+int drm_topaz_pmpolicy = PSB_PMPOLICY_NOPM;
+int drm_topaz_sbuswa;
+int drm_psb_ospm = 1;
+int drm_psb_gl3_enable = 1;
+int drm_psb_topaz_clockgating = 0;
+#ifdef CONFIG_PM_RUNTIME
+int gfxrtdelay = 0;
+#endif
+static int PanelID = GCT_DETECT;
+char HDMI_EDID[HDMI_MONITOR_NAME_LENGTH];
+
+static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(no_fb, "Disable FBdev");
+MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
+MODULE_PARM_DESC(disable_vsync, "Disable vsync interrupts");
+MODULE_PARM_DESC(force_pipeb, "Forces PIPEB to become primary fb");
+MODULE_PARM_DESC(ta_mem_size, "TA memory size in kiB");
+MODULE_PARM_DESC(ospm, "switch for ospm support");
+MODULE_PARM_DESC(gl3_enabled, "Enable GL3 cache");
+MODULE_PARM_DESC(rtpm, "Specifies Runtime PM delay for GFX");
+MODULE_PARM_DESC(msvdx_pmpolicy, "msvdx power management policy btw frames");
+MODULE_PARM_DESC(topaz_pmpolicy, "topaz power managerment policy btw frames");
+MODULE_PARM_DESC(topaz_sbuswa, "WA for topaz sysbus write");
+MODULE_PARM_DESC(PanelID, "Panel info for querying");
+MODULE_PARM_DESC(hdmi_edid, "EDID info for HDMI monitor");
+MODULE_PARM_DESC(cpu_relax, "replace udelay with cpurelax for video");
+MODULE_PARM_DESC(udelay_multiplier, "the multiplier of the usec of video udelay");
+MODULE_PARM_DESC(udelay_divider, "the divider of the usec of video udelay");
+
+module_param_named(debug, drm_psb_debug, int, 0600);
+module_param_named(no_fb, drm_psb_no_fb, int, 0600);
+module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
+module_param_named(force_pipeb, drm_psb_force_pipeb, int, 0600);
+module_param_named(msvdx_pmpolicy, drm_msvdx_pmpolicy, int, 0600);
+module_param_named(cpu_relax, drm_psb_cpurelax, int, 0600);
+module_param_named(udelay_multiplier, drm_psb_udelaymultiplier, int, 0600);
+module_param_named(udelay_divider, drm_psb_udelaydivider, int, 0600);
+module_param_named(topaz_pmpolicy, drm_topaz_pmpolicy, int, 0600);
+module_param_named(topaz_sbuswa, drm_topaz_sbuswa, int, 0600);
+module_param_named(ospm, drm_psb_ospm, int, 0600);
+module_param_named(gl3_enabled, drm_psb_gl3_enable, int, 0600);
+#ifdef CONFIG_PM_RUNTIME
+module_param_named(rtpm, gfxrtdelay, int, 0600);
+#endif
+module_param_named(topaz_clockgating, drm_psb_topaz_clockgating, int, 0600);
+module_param_named(PanelID, PanelID, int, 0600);
+module_param_string(hdmi_edid, HDMI_EDID, 20, 0600);
+#ifndef MODULE
+/* Make ospm configurable via cmdline firstly, and others can be enabled if needed. */
+static int __init config_ospm(char *arg)
+{
+       /* ospm turn on/off control can be passed in as a cmdline parameter */
+       /* to enable this feature add ospm=1 to cmdline */
+       /* to disable this feature add ospm=0 to cmdline */
+       if (!arg)
+               return -EINVAL;
+
+       if (!strcasecmp(arg, "0"))
+               drm_psb_ospm = 0;
+       else if (!strcasecmp(arg, "1"))
+               drm_psb_ospm = 1;
+
+       return 0;
+}
+static int __init config_gl3(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
+
+       if (!strcasecmp(arg, "0"))
+               drm_psb_gl3_enable = 0;
+       else if (!strcasecmp(arg, "1"))
+               drm_psb_gl3_enable = 1;
+
+       return 0;
+}
+early_param("ospm", config_ospm);
+early_param("gl3_enabled", config_gl3);
+#endif
+
+static struct pci_device_id pciidlist[] = {
+#ifdef SGX535
+       {0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+       {0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+       {0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+       {0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+       {0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+       {0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+       {0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+       {0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+#endif
+#ifdef SGX540
+       {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+       {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+       {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+       {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+       {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+       {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+       {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+       {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+#endif
+       {0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, pciidlist);
+/*
+ * Standard IOCTLs.
+ */
+
+#define DRM_IOCTL_PSB_KMS_OFF  \
+               DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_KMS_ON   \
+               DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_VT_LEAVE \
+               DRM_IO(DRM_PSB_VT_LEAVE + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_VT_ENTER \
+               DRM_IO(DRM_PSB_VT_ENTER + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_EXTENSION        \
+               DRM_IOWR(DRM_PSB_EXTENSION + DRM_COMMAND_BASE, \
+                        union drm_psb_extension_arg)
+#define DRM_IOCTL_PSB_SIZES    \
+               DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
+                       struct drm_psb_sizes_arg)
+#define DRM_IOCTL_PSB_FUSE_REG \
+               DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
+#define DRM_IOCTL_PSB_VBT      \
+               DRM_IOWR(DRM_PSB_VBT + DRM_COMMAND_BASE, \
+                       struct gct_ioctl_arg)
+#define DRM_IOCTL_PSB_DC_STATE \
+               DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
+                       struct drm_psb_dc_state_arg)
+#define DRM_IOCTL_PSB_ADB      \
+               DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
+#define DRM_IOCTL_PSB_MODE_OPERATION   \
+               DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
+                        struct drm_psb_mode_operation_arg)
+#define DRM_IOCTL_PSB_STOLEN_MEMORY    \
+               DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
+                        struct drm_psb_stolen_memory_arg)
+#define DRM_IOCTL_PSB_REGISTER_RW      \
+               DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \
+                        struct drm_psb_register_rw_arg)
+#define DRM_IOCTL_PSB_GTT_MAP  \
+               DRM_IOWR(DRM_PSB_GTT_MAP + DRM_COMMAND_BASE, \
+                        struct psb_gtt_mapping_arg)
+#define DRM_IOCTL_PSB_GTT_UNMAP        \
+               DRM_IOW(DRM_PSB_GTT_UNMAP + DRM_COMMAND_BASE, \
+                       struct psb_gtt_mapping_arg)
+#define DRM_IOCTL_PSB_GETPAGEADDRS     \
+               DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_GETPAGEADDRS,\
+                        struct drm_psb_getpageaddrs_arg)
+#define DRM_IOCTL_PSB_HIST_ENABLE      \
+               DRM_IOWR(DRM_PSB_HIST_ENABLE + DRM_COMMAND_BASE, \
+                        uint32_t)
+#define DRM_IOCTL_PSB_HIST_STATUS      \
+               DRM_IOWR(DRM_PSB_HIST_STATUS + DRM_COMMAND_BASE, \
+                        struct drm_psb_hist_status_arg)
+#define DRM_IOCTL_PSB_UPDATE_GUARD     \
+               DRM_IOWR(DRM_PSB_UPDATE_GUARD + DRM_COMMAND_BASE, \
+                        uint32_t)
+#define DRM_IOCTL_PSB_INIT_COMM        \
+               DRM_IOWR(DRM_PSB_INIT_COMM + DRM_COMMAND_BASE, \
+                        uint32_t)
+#define DRM_IOCTL_PSB_DPST     \
+               DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
+                        uint32_t)
+#define DRM_IOCTL_PSB_GAMMA    \
+               DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
+                        struct drm_psb_dpst_lut_arg)
+#define DRM_IOCTL_PSB_DPST_BL  \
+               DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
+                        uint32_t)
+#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID    \
+               DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
+                        struct drm_psb_get_pipe_from_crtc_id_arg)
+
+/*pvr ioctls*/
+#define PVR_DRM_SRVKM_IOCTL \
+       DRM_IOW(DRM_COMMAND_BASE + PVR_DRM_SRVKM_CMD, \
+               PVRSRV_BRIDGE_PACKAGE)
+#define PVR_DRM_DISP_IOCTL \
+       DRM_IO(DRM_COMMAND_BASE + PVR_DRM_DISP_CMD)
+#define PVR_DRM_BC_IOCTL \
+       DRM_IO(DRM_COMMAND_BASE + PVR_DRM_BC_CMD)
+#define PVR_DRM_IS_MASTER_IOCTL \
+       DRM_IO(DRM_COMMAND_BASE + PVR_DRM_IS_MASTER_CMD)
+#define PVR_DRM_UNPRIV_IOCTL \
+       DRM_IOWR(DRM_COMMAND_BASE + PVR_DRM_UNPRIV_CMD, \
+               IMG_UINT32)
+#if defined(PDUMP)
+#define PVR_DRM_DBGDRV_IOCTL \
+       DRM_IOW(DRM_COMMAND_BASE + PVR_DRM_DBGDRV_CMD, IOCTL_PACKAGE)
+#endif
+
+/*DPU/DSR stuff*/
+#define DRM_IOCRL_PSB_DPU_QUERY DRM_IOR(DRM_PSB_DPU_QUERY + DRM_COMMAND_BASE, IMG_UINT32)
+#define DRM_IOCRL_PSB_DPU_DSR_ON DRM_IOW(DRM_PSB_DPU_DSR_ON + DRM_COMMAND_BASE, IMG_UINT32)
+#define DRM_IOCRL_PSB_DPU_DSR_OFF DRM_IOW(DRM_PSB_DPU_DSR_OFF + DRM_COMMAND_BASE, struct drm_psb_drv_dsr_off_arg)
+
+/*
+ * TTM execbuf extension.
+ */
+#if defined(PDUMP)
+#define DRM_PSB_CMDBUF           (PVR_DRM_DBGDRV_CMD + 1)
+#else
+#define DRM_PSB_CMDBUF           (DRM_PSB_DPU_DSR_OFF + 1)
+/* #define DRM_PSB_CMDBUF                (DRM_PSB_DPST_BL + 1) */
+#endif
+
+#define DRM_PSB_SCENE_UNREF      (DRM_PSB_CMDBUF + 1)
+#define DRM_IOCTL_PSB_CMDBUF   \
+               DRM_IOW(DRM_PSB_CMDBUF + DRM_COMMAND_BASE,      \
+                       struct drm_psb_cmdbuf_arg)
+/*
+ * TTM placement user extension.
+ */
+
+#define DRM_PSB_PLACEMENT_OFFSET   (DRM_PSB_SCENE_UNREF + 1)
+
+#define DRM_PSB_TTM_PL_CREATE   (TTM_PL_CREATE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_REFERENCE (TTM_PL_REFERENCE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_UNREF    (TTM_PL_UNREF + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_SYNCCPU  (TTM_PL_SYNCCPU + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_WAITIDLE  (TTM_PL_WAITIDLE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_SETSTATUS (TTM_PL_SETSTATUS + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_CREATE_UB (TTM_PL_CREATE_UB + DRM_PSB_PLACEMENT_OFFSET)
+
+/*
+ * TTM fence extension.
+ */
+
+#define DRM_PSB_FENCE_OFFSET      (DRM_PSB_TTM_PL_CREATE_UB + 1)
+#define DRM_PSB_TTM_FENCE_SIGNALED (TTM_FENCE_SIGNALED + DRM_PSB_FENCE_OFFSET)
+#define DRM_PSB_TTM_FENCE_FINISH   (TTM_FENCE_FINISH + DRM_PSB_FENCE_OFFSET)
+#define DRM_PSB_TTM_FENCE_UNREF    (TTM_FENCE_UNREF + DRM_PSB_FENCE_OFFSET)
+
+#define DRM_PSB_FLIP      (DRM_PSB_TTM_FENCE_UNREF + 1)        /*20*/
+/* PSB video extension */
+#define DRM_LNC_VIDEO_GETPARAM         (DRM_PSB_FLIP + 1)
+
+/*BC_VIDEO ioctl*/
+#define DRM_BUFFER_CLASS_VIDEO      (DRM_LNC_VIDEO_GETPARAM + 1)    /*0x32*/
+
+#define DRM_IOCTL_PSB_TTM_PL_CREATE    \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE,\
+                union ttm_pl_create_arg)
+#define DRM_IOCTL_PSB_TTM_PL_REFERENCE \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_REFERENCE,\
+                union ttm_pl_reference_arg)
+#define DRM_IOCTL_PSB_TTM_PL_UNREF    \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_UNREF,\
+               struct ttm_pl_reference_req)
+#define DRM_IOCTL_PSB_TTM_PL_SYNCCPU   \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SYNCCPU,\
+               struct ttm_pl_synccpu_arg)
+#define DRM_IOCTL_PSB_TTM_PL_WAITIDLE   \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_WAITIDLE,\
+               struct ttm_pl_waitidle_arg)
+#define DRM_IOCTL_PSB_TTM_PL_SETSTATUS \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SETSTATUS,\
+                union ttm_pl_setstatus_arg)
+#define DRM_IOCTL_PSB_TTM_PL_CREATE_UB    \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE_UB,\
+                union ttm_pl_create_ub_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_SIGNALED \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_SIGNALED, \
+                 union ttm_fence_signaled_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_FINISH \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_FINISH,   \
+                union ttm_fence_finish_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_UNREF \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_UNREF,     \
+                struct ttm_fence_unref_arg)
+#define DRM_IOCTL_PSB_FLIP \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_FLIP, \
+                struct drm_psb_pageflip_arg)
+#define DRM_IOCTL_LNC_VIDEO_GETPARAM \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_LNC_VIDEO_GETPARAM, \
+                struct drm_lnc_video_getparam_arg)
+
+/*bc_video ioctl*/
+#define DRM_IOCTL_BUFFER_CLASS_VIDEO \
+        DRM_IOWR(DRM_COMMAND_BASE + DRM_BUFFER_CLASS_VIDEO, \
+             BC_Video_ioctl_package)
+
+static int psb_vt_leave_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+static int psb_vt_enter_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+static int psb_sizes_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+static int psb_fuse_reg_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+static int psb_vbt_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+                             struct drm_file *file_priv);
+static int psb_adb_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv);
+static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+static int psb_hist_enable_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+static int psb_hist_status_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+static int psb_update_guard_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv);
+static int psb_init_comm_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv);
+static int psb_dpst_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+static int psb_gamma_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv);
+static int psb_dpu_query_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv);
+static int psb_dpu_dsr_on_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+
+static int psb_dpu_dsr_off_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+
+#define PSB_IOCTL_DEF(ioctl, func, flags) \
+       [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
+
+static struct drm_ioctl_desc psb_ioctls[] = {
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_OFF, psbfb_kms_off_ioctl,
+       DRM_ROOT_ONLY),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_ON,
+       psbfb_kms_on_ioctl,
+       DRM_ROOT_ONLY),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_LEAVE, psb_vt_leave_ioctl,
+       DRM_ROOT_ONLY),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_ENTER,
+       psb_vt_enter_ioctl,
+       DRM_ROOT_ONLY),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_EXTENSION, psb_extension_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_FUSE_REG, psb_fuse_reg_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_VBT, psb_vbt_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_MAP,
+       psb_gtt_map_meminfo_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_UNMAP,
+       psb_gtt_unmap_meminfo_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GETPAGEADDRS,
+       psb_getpageaddrs_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, 0),
+       PSB_IOCTL_DEF(PVR_DRM_DISP_IOCTL, PVRDRM_Dummy_ioctl, 0),
+       PSB_IOCTL_DEF(PVR_DRM_BC_IOCTL, PVRDRM_Dummy_ioctl, 0),
+       PSB_IOCTL_DEF(PVR_DRM_IS_MASTER_IOCTL, PVRDRMIsMaster, DRM_MASTER),
+       PSB_IOCTL_DEF(PVR_DRM_UNPRIV_IOCTL, PVRDRMUnprivCmd, 0),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_HIST_ENABLE,
+       psb_hist_enable_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_HIST_STATUS,
+       psb_hist_status_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_UPDATE_GUARD, psb_update_guard_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_INIT_COMM, psb_init_comm_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID, psb_intel_get_pipe_from_crtc_id, 0),
+#if defined(PDUMP)
+       PSB_IOCTL_DEF(PVR_DRM_DBGDRV_IOCTL, SYSPVRDBGDrivIoctl, 0),
+#endif
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_CMDBUF, psb_cmdbuf_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE, psb_pl_create_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_REFERENCE, psb_pl_reference_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_UNREF, psb_pl_unref_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SYNCCPU, psb_pl_synccpu_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_WAITIDLE, psb_pl_waitidle_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SETSTATUS, psb_pl_setstatus_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE_UB, psb_pl_ub_create_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_SIGNALED,
+       psb_fence_signaled_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_FINISH, psb_fence_finish_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_UNREF, psb_fence_unref_ioctl,
+       DRM_AUTH),
+       /*to be removed later */
+       /*PSB_IOCTL_DEF(DRM_IOCTL_PSB_FLIP, psb_page_flip, DRM_AUTH),*/
+       PSB_IOCTL_DEF(DRM_IOCTL_LNC_VIDEO_GETPARAM,
+       lnc_video_getparam, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_BUFFER_CLASS_VIDEO,
+       BC_Video_Bridge, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCRL_PSB_DPU_QUERY, psb_dpu_query_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCRL_PSB_DPU_DSR_ON, psb_dpu_dsr_on_ioctl,
+       DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCRL_PSB_DPU_DSR_OFF, psb_dpu_dsr_off_ioctl,
+       DRM_AUTH)
+};
+
+static void psb_set_uopt(struct drm_psb_uopt *uopt)
+{
+       return;
+}
+
+static void psb_lastclose(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+
+       return;
+
+       if (!dev->dev_private)
+               return;
+
+       mutex_lock(&dev_priv->cmdbuf_mutex);
+       if (dev_priv->context.buffers) {
+               vfree(dev_priv->context.buffers);
+               dev_priv->context.buffers = NULL;
+       }
+       mutex_unlock(&dev_priv->cmdbuf_mutex);
+}
+
+static void psb_do_takedown(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct ttm_bo_device *bdev = &dev_priv->bdev;
+
+
+       if (dev_priv->have_mem_mmu) {
+               ttm_bo_clean_mm(bdev, DRM_PSB_MEM_MMU);
+               dev_priv->have_mem_mmu = 0;
+       }
+
+       if (dev_priv->have_tt) {
+               ttm_bo_clean_mm(bdev, TTM_PL_TT);
+               dev_priv->have_tt = 0;
+       }
+
+       if (dev_priv->have_camera) {
+               ttm_bo_clean_mm(bdev, TTM_PL_CI);
+               dev_priv->have_camera = 0;
+       }
+       if (dev_priv->have_rar) {
+               ttm_bo_clean_mm(bdev, TTM_PL_RAR);
+               dev_priv->have_rar = 0;
+       }
+
+       psb_msvdx_uninit(dev);
+       pnw_topaz_uninit(dev);
+}
+
+#define FB_REG06 0xD0810600
+#define FB_TOPAZ_DISABLE BIT(0)
+#define FB_MIPI_DISABLE  BIT(11)
+#define FB_REG09 0xD0810900
+#define FB_SKU_MASK  (BIT(12)|BIT(13)|BIT(14))
+#define FB_SKU_SHIFT 12
+#define FB_SKU_100 0
+#define FB_SKU_100L 1
+#define FB_SKU_83 2
+#if 1 /* FIXME remove it after PO */
+#define FB_GFX_CLK_DIVIDE_MASK (BIT(20)|BIT(21)|BIT(22))
+#define FB_GFX_CLK_DIVIDE_SHIFT 20
+#define FB_VED_CLK_DIVIDE_MASK (BIT(23)|BIT(24))
+#define FB_VED_CLK_DIVIDE_SHIFT 23
+#define FB_VEC_CLK_DIVIDE_MASK (BIT(25)|BIT(26))
+#define FB_VEC_CLK_DIVIDE_SHIFT 25
+#endif /* FIXME remove it after PO */
+
+
+void mrst_get_fuse_settings(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+       uint32_t fuse_value = 0;
+       uint32_t fuse_value_tmp = 0;
+
+       pci_write_config_dword(pci_root, 0xD0, FB_REG06);
+       pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+       dev_priv->iLVDS_enable = 0;
+
+       DRM_INFO("internal display is %s\n",
+                dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
+
+       /*prevent Runtime suspend at start*/
+       if (dev_priv->iLVDS_enable) {
+               dev_priv->is_lvds_on = true;
+               dev_priv->is_mipi_on = false;
+       } else {
+               dev_priv->is_mipi_on = true;
+               dev_priv->is_lvds_on = false;
+       }
+
+       if (dev_priv->dev->pci_device == PCI_ID_TOPAZ_DISABLED)
+               dev_priv->topaz_disabled = 1;
+       else
+               dev_priv->topaz_disabled = 0;
+
+       dev_priv->video_device_fuse = fuse_value;
+
+       DRM_INFO("topaz is %s\n",
+                dev_priv->topaz_disabled ? "disabled" : "enabled");
+
+       pci_write_config_dword(pci_root, 0xD0, FB_REG09);
+       pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+       DRM_INFO("SKU values is 0x%x. \n", fuse_value);
+       fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
+
+       dev_priv->fuse_reg_value = fuse_value;
+
+       switch (fuse_value_tmp) {
+       case FB_SKU_100:
+               dev_priv->core_freq = 200;
+               break;
+       case FB_SKU_100L:
+               dev_priv->core_freq = 100;
+               break;
+       case FB_SKU_83:
+               dev_priv->core_freq = 166;
+               break;
+       default:
+               DRM_ERROR("Invalid SKU values, SKU value = 0x%08x\n", fuse_value_tmp);
+               dev_priv->core_freq = 0;
+       }
+       DRM_INFO("LNC core clk is %dMHz.\n", dev_priv->core_freq);
+
+#if 1 /* FIXME remove it after PO */
+       fuse_value_tmp =
+               (fuse_value & FB_GFX_CLK_DIVIDE_MASK) >> FB_GFX_CLK_DIVIDE_SHIFT;
+
+       switch (fuse_value_tmp) {
+       case 0:
+               DRM_INFO("Gfx clk : core clk = 1:1. \n");
+               break;
+       case 1:
+               DRM_INFO("Gfx clk : core clk = 4:3. \n");
+               break;
+       case 2:
+               DRM_INFO("Gfx clk : core clk = 8:5. \n");
+               break;
+       case 3:
+               DRM_INFO("Gfx clk : core clk = 2:1. \n");
+               break;
+       case 4:
+               DRM_INFO("Gfx clk : core clk = 16:7. \n");
+               break;
+       case 5:
+               DRM_INFO("Gfx clk : core clk = 8:3. \n");
+               break;
+       case 6:
+               DRM_INFO("Gfx clk : core clk = 16:5. \n");
+               break;
+       case 7:
+               DRM_INFO("Gfx clk : core clk = 4:1. \n");
+               break;
+       default:
+               DRM_ERROR("Invalid GFX CLK DIVIDE values, value = 0x%08x\n",
+                         fuse_value_tmp);
+       }
+
+       fuse_value_tmp =
+               (fuse_value & FB_VED_CLK_DIVIDE_MASK) >> FB_VED_CLK_DIVIDE_SHIFT;
+
+       switch (fuse_value_tmp) {
+       case 0:
+               DRM_INFO("Ved clk : core clk = 1:1. \n");
+               break;
+       case 1:
+               DRM_INFO("Ved clk : core clk = 4:3. \n");
+               break;
+       case 2:
+               DRM_INFO("Ved clk : core clk = 8:5. \n");
+               break;
+       case 3:
+               DRM_INFO("Ved clk : core clk = 2:1. \n");
+               break;
+       default:
+               DRM_ERROR("Invalid VED CLK DIVIDE values, value = 0x%08x\n",
+                         fuse_value_tmp);
+       }
+
+       fuse_value_tmp =
+               (fuse_value & FB_VEC_CLK_DIVIDE_MASK) >> FB_VEC_CLK_DIVIDE_SHIFT;
+
+       switch (fuse_value_tmp) {
+       case 0:
+               DRM_INFO("Vec clk : core clk = 1:1. \n");
+               break;
+       case 1:
+               DRM_INFO("Vec clk : core clk = 4:3. \n");
+               break;
+       case 2:
+               DRM_INFO("Vec clk : core clk = 8:5. \n");
+               break;
+       case 3:
+               DRM_INFO("Vec clk : core clk = 2:1. \n");
+               break;
+       default:
+               DRM_ERROR("Invalid VEC CLK DIVIDE values, value = 0x%08x\n",
+                         fuse_value_tmp);
+       }
+#endif /* FIXME remove it after PO */
+
+#if KSEL_BYPASS_83_100_ENABLE
+       dev_priv->ksel = KSEL_BYPASS_83_100;
+#endif /* KSEL_BYPASS_83_100_ENABLE */
+
+#if  KSEL_CRYSTAL_19_ENABLED
+       dev_priv->ksel = KSEL_CRYSTAL_19;
+#endif /*  KSEL_CRYSTAL_19_ENABLED */
+
+       return;
+}
+
+bool mid_get_pci_revID(struct drm_psb_private *dev_priv)
+{
+       uint32_t platform_rev_id = 0;
+       struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+       /*get the revison ID, B0:D2:F0;0x08 */
+       pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
+       dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
+       pci_dev_put(pci_gfx_root);
+       PSB_DEBUG_ENTRY("platform_rev_id is %x\n",      dev_priv->platform_rev_id);
+
+       return true;
+}
+
+bool mrst_get_vbt_data(struct drm_psb_private *dev_priv)
+{
+       struct mrst_vbt *pVBT = &dev_priv->vbt_data;
+       u32 platform_config_address;
+       u16 new_size;
+       u8 *pVBT_virtual;
+       u8 bpi;
+       u8 number_desc = 0;
+       struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
+       struct gct_r10_timing_info ti;
+       void *pGCT;
+       struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+       /*get the address of the platform config vbt, B0:D2:F0;0xFC */
+       pci_read_config_dword(pci_gfx_root, 0xFC, &platform_config_address);
+       pci_dev_put(pci_gfx_root);
+       DRM_INFO("drm platform config address is %x\n",
+                platform_config_address);
+
+       /* check for platform config address == 0. */
+       /* this means fw doesn't support vbt */
+
+       if (platform_config_address == 0) {
+               pVBT->Size = 0;
+               return false;
+       }
+
+       /* get the virtual address of the vbt */
+       pVBT_virtual = ioremap(platform_config_address, sizeof(*pVBT));
+
+       memcpy(pVBT, pVBT_virtual, sizeof(*pVBT));
+       iounmap(pVBT_virtual); /* Free virtual address space */
+
+       printk(KERN_ALERT "GCT Revision is %x\n", pVBT->Revision);
+
+       switch (pVBT->Revision) {
+       case 0:
+               pVBT->mrst_gct = NULL;
+               pVBT->mrst_gct = \
+                                ioremap(platform_config_address + sizeof(*pVBT) - 4,
+                                        pVBT->Size - sizeof(*pVBT) + 4);
+               pGCT = pVBT->mrst_gct;
+               bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
+               dev_priv->gct_data.bpi = bpi;
+               dev_priv->gct_data.pt =
+                       ((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
+               memcpy(&dev_priv->gct_data.DTD,
+                      &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
+                      sizeof(struct mrst_timing_info));
+               dev_priv->gct_data.Panel_Port_Control =
+                       ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
+               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+                       ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+               break;
+       case 1:
+               pVBT->mrst_gct = NULL;
+               pVBT->mrst_gct = \
+                                ioremap(platform_config_address + sizeof(*pVBT) - 4,
+                                        pVBT->Size - sizeof(*pVBT) + 4);
+               pGCT = pVBT->mrst_gct;
+               bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
+               dev_priv->gct_data.bpi = bpi;
+               dev_priv->gct_data.pt =
+                       ((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
+               memcpy(&dev_priv->gct_data.DTD,
+                      &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
+                      sizeof(struct mrst_timing_info));
+               dev_priv->gct_data.Panel_Port_Control =
+                       ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
+               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+                       ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+               break;
+       case 0x10:
+               /*header definition changed from rev 01 (v2) to rev 10h. */
+               /*so, some values have changed location*/
+               new_size = pVBT->Checksum; /*checksum contains lo size byte*/
+               /*LSB of mrst_gct contains hi size byte*/
+               new_size |= ((0xff & (unsigned int)pVBT->mrst_gct)) << 8;
+
+               pVBT->Checksum = pVBT->Size; /*size contains the checksum*/
+               if (new_size > 0xff)
+                       pVBT->Size = 0xff; /*restrict size to 255*/
+               else
+                       pVBT->Size = new_size;
+
+               /* number of descriptors defined in the GCT */
+               number_desc = ((0xff00 & (unsigned int)pVBT->mrst_gct)) >> 8;
+               bpi = ((0xff0000 & (unsigned int)pVBT->mrst_gct)) >> 16;
+               pVBT->mrst_gct = NULL;
+               pVBT->mrst_gct = \
+                                ioremap(platform_config_address + GCT_R10_HEADER_SIZE,
+                                        GCT_R10_DISPLAY_DESC_SIZE * number_desc);
+               pGCT = pVBT->mrst_gct;
+               pGCT = (u8 *)pGCT + (bpi * GCT_R10_DISPLAY_DESC_SIZE);
+               dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
+
+               /*copy the GCT display timings into a temp structure*/
+               memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
+
+               /*now copy the temp struct into the dev_priv->gct_data*/
+               dp_ti->pixel_clock = ti.pixel_clock;
+               dp_ti->hactive_hi = ti.hactive_hi;
+               dp_ti->hactive_lo = ti.hactive_lo;
+               dp_ti->hblank_hi = ti.hblank_hi;
+               dp_ti->hblank_lo = ti.hblank_lo;
+               dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
+               dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
+               dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
+               dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
+               dp_ti->vactive_hi = ti.vactive_hi;
+               dp_ti->vactive_lo = ti.vactive_lo;
+               dp_ti->vblank_hi = ti.vblank_hi;
+               dp_ti->vblank_lo = ti.vblank_lo;
+               dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
+               dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
+               dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
+               dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
+
+               /*mov the MIPI_Display_Descriptor data from GCT to dev priv*/
+               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+                       *((u8 *)pGCT + 0x0d);
+               dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
+                       (*((u8 *)pGCT + 0x0e)) << 8;
+               break;
+       default:
+               printk(KERN_ALERT "Unknown revision of GCT!\n");
+               pVBT->Size = 0;
+               return false;
+       }
+
+       if (PanelID == GCT_DETECT) {
+               if (dev_priv->gct_data.bpi == 0) {
+                       PSB_DEBUG_ENTRY("[GFX] TMD Panel Detected.\n");
+                       dev_priv->panel_id = TMD_VID;
+                       PanelID = TMD_VID;
+               } else {
+                       PSB_DEBUG_ENTRY("[GFX] Default Panel (TPO)\n");
+                       dev_priv->panel_id = TPO_CMD;
+                       PanelID = TPO_CMD;
+               }
+       } else {
+               PSB_DEBUG_ENTRY("[GFX] Panel Parameter Passed in through cmd line\n");
+               dev_priv->panel_id = PanelID;
+       }
+
+       return true;
+}
+
+static int psb_do_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct ttm_bo_device *bdev = &dev_priv->bdev;
+       struct psb_gtt *pg = dev_priv->pg;
+
+       uint32_t stolen_gtt;
+       uint32_t tt_start;
+       uint32_t tt_pages;
+
+       int ret = -ENOMEM;
+
+
+       /*
+        * Initialize sequence numbers for the different command
+        * submission mechanisms.
+        */
+
+       dev_priv->sequence[PSB_ENGINE_2D] = 0;
+       dev_priv->sequence[PSB_ENGINE_VIDEO] = 1;
+       dev_priv->sequence[LNC_ENGINE_ENCODE] = 0;
+
+       if (pg->mmu_gatt_start & 0x0FFFFFFF) {
+               DRM_ERROR("Gatt must be 256M aligned. This is a bug.\n");
+               ret = -EINVAL;
+               goto out_err;
+       }
+
+       stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
+       stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       stolen_gtt =
+               (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
+
+       dev_priv->gatt_free_offset = pg->mmu_gatt_start +
+                                    (stolen_gtt << PAGE_SHIFT) * 1024;
+
+       if (1 || drm_debug) {
+               uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID);
+               uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION);
+               DRM_INFO("SGX core id = 0x%08x\n", core_id);
+               DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n",
+                        (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >>
+                        _PSB_CC_REVISION_MAJOR_SHIFT,
+                        (core_rev & _PSB_CC_REVISION_MINOR_MASK) >>
+                        _PSB_CC_REVISION_MINOR_SHIFT);
+               DRM_INFO
+               ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n",
+                (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >>
+                _PSB_CC_REVISION_MAINTENANCE_SHIFT,
+                (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >>
+                _PSB_CC_REVISION_DESIGNER_SHIFT);
+       }
+
+       spin_lock_init(&dev_priv->irqmask_lock);
+
+       tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+                  pg->gatt_pages : PSB_TT_PRIV0_PLIMIT;
+       tt_start = dev_priv->gatt_free_offset - pg->mmu_gatt_start;
+       tt_pages -= tt_start >> PAGE_SHIFT;
+       dev_priv->sizes.ta_mem_size = 0;
+
+       /* TT region managed by TTM. */
+       if (!ttm_bo_init_mm(bdev, TTM_PL_TT,
+                           pg->gatt_pages -
+                           (pg->ci_start >> PAGE_SHIFT) -
+                           ((dev_priv->ci_region_size + dev_priv->rar_region_size)
+                            >> PAGE_SHIFT))) {
+
+               dev_priv->have_tt = 1;
+               dev_priv->sizes.tt_size =
+                       (tt_pages << PAGE_SHIFT) / (1024 * 1024) / 2;
+       }
+
+       if (!ttm_bo_init_mm(bdev,
+                           DRM_PSB_MEM_MMU,
+                           PSB_MEM_TT_START >> PAGE_SHIFT)) {
+               dev_priv->have_mem_mmu = 1;
+               dev_priv->sizes.mmu_size =
+                       PSB_MEM_TT_START / (1024 * 1024);
+       }
+
+
+       PSB_DEBUG_INIT("Init MSVDX\n");
+       psb_msvdx_init(dev);
+
+       PSB_DEBUG_INIT("Init Topaz\n");
+       /* for sku100L and sku100M, VEC is disabled in fuses */
+       pnw_topaz_init(dev);
+
+       return 0;
+out_err:
+       psb_do_takedown(dev);
+       return ret;
+}
+
+static int psb_driver_unload(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+
+       /*Fristly, unload pvr driver*/
+       PVRSRVDrmUnload(dev);
+
+       /*TODO: destroy DSR/DPU infos here*/
+       psb_backlight_exit(); /*writes minimum value to backlight HW reg */
+
+       if (drm_psb_no_fb == 0)
+               psb_modeset_cleanup(dev);
+
+       if (dev_priv) {
+               psb_do_takedown(dev);
+
+               if (dev_priv->pf_pd) {
+                       psb_mmu_free_pagedir(dev_priv->pf_pd);
+                       dev_priv->pf_pd = NULL;
+               }
+               if (dev_priv->mmu) {
+                       struct psb_gtt *pg = dev_priv->pg;
+
+                       down_read(&pg->sem);
+                       psb_mmu_remove_pfn_sequence(
+                               psb_mmu_get_default_pd
+                               (dev_priv->mmu),
+                               pg->mmu_gatt_start,
+                               pg->vram_stolen_size >> PAGE_SHIFT);
+                       if (pg->ci_stolen_size != 0)
+                               psb_mmu_remove_pfn_sequence(
+                                       psb_mmu_get_default_pd
+                                       (dev_priv->mmu),
+                                       pg->ci_start,
+                                       pg->ci_stolen_size >> PAGE_SHIFT);
+                       if (pg->rar_stolen_size != 0)
+                               psb_mmu_remove_pfn_sequence(
+                                       psb_mmu_get_default_pd
+                                       (dev_priv->mmu),
+                                       pg->rar_start,
+                                       pg->rar_stolen_size >> PAGE_SHIFT);
+                       up_read(&pg->sem);
+                       psb_mmu_driver_takedown(dev_priv->mmu);
+                       dev_priv->mmu = NULL;
+               }
+               psb_gtt_takedown(dev_priv->pg, 1);
+               if (dev_priv->scratch_page) {
+                       __free_page(dev_priv->scratch_page);
+                       dev_priv->scratch_page = NULL;
+               }
+               if (dev_priv->has_bo_device) {
+                       ttm_bo_device_release(&dev_priv->bdev);
+                       dev_priv->has_bo_device = 0;
+               }
+               if (dev_priv->has_fence_device) {
+                       ttm_fence_device_release(&dev_priv->fdev);
+                       dev_priv->has_fence_device = 0;
+               }
+               if (dev_priv->vdc_reg) {
+                       iounmap(dev_priv->vdc_reg);
+                       dev_priv->vdc_reg = NULL;
+               }
+               if (dev_priv->sgx_reg) {
+                       iounmap(dev_priv->sgx_reg);
+                       dev_priv->sgx_reg = NULL;
+               }
+#ifdef CONFIG_MDFD_GL3
+               iounmap(dev_priv->gl3_reg);
+               dev_priv->gl3_reg = NULL;
+#endif
+
+               if (dev_priv->msvdx_reg) {
+                       iounmap(dev_priv->msvdx_reg);
+                       dev_priv->msvdx_reg = NULL;
+               }
+
+               if (dev_priv->topaz_reg) {
+                       iounmap(dev_priv->topaz_reg);
+                       dev_priv->topaz_reg = NULL;
+               }
+
+               if (dev_priv->tdev)
+                       ttm_object_device_release(&dev_priv->tdev);
+
+               if (dev_priv->has_global)
+                       psb_ttm_global_release(dev_priv);
+
+               kfree(dev_priv);
+               dev->dev_private = NULL;
+       }
+
+       ospm_power_uninit();
+
+       return 0;
+}
+
+static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+       struct drm_psb_private *dev_priv;
+       struct ttm_bo_device *bdev;
+       unsigned long resource_start;
+       struct psb_gtt *pg;
+       unsigned long irqflags;
+       int ret = -ENOMEM;
+       uint32_t tt_pages;
+       struct pci_dev *pdev;
+       struct device *ddev;
+       struct kobject *kobj;
+
+       DRM_INFO("psb - %s\n", PSB_PACKAGE_VERSION);
+
+       dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       DRM_INFO("Run drivers on Medfield platform!\n");
+
+       INIT_LIST_HEAD(&dev_priv->video_ctx);
+
+       dev_priv->num_pipe = 3;
+
+       /*init DPST umcomm to NULL*/
+       dev_priv->psb_dpst_state = NULL;
+       dev_priv->psb_hotplug_state = NULL;
+       dev_priv->hdmi_done_reading_edid = false;
+       dev_priv->xserver_start = false;
+
+       dev_priv->dev = dev;
+       bdev = &dev_priv->bdev;
+
+       ret = psb_ttm_global_init(dev_priv);
+       if (unlikely(ret != 0))
+               goto out_err;
+       dev_priv->has_global = 1;
+
+       dev_priv->tdev = ttm_object_device_init
+                        (dev_priv->mem_global_ref.object, PSB_OBJECT_HASH_ORDER);
+       if (unlikely(dev_priv->tdev == NULL))
+               goto out_err;
+
+       mutex_init(&dev_priv->temp_mem);
+       mutex_init(&dev_priv->cmdbuf_mutex);
+       mutex_init(&dev_priv->reset_mutex);
+       INIT_LIST_HEAD(&dev_priv->context.validate_list);
+       INIT_LIST_HEAD(&dev_priv->context.kern_validate_list);
+
+       mutex_init(&dev_priv->dsr_mutex);
+
+       spin_lock_init(&dev_priv->reloc_lock);
+
+       DRM_INIT_WAITQUEUE(&dev_priv->rel_mapped_queue);
+
+       dev->dev_private = (void *) dev_priv;
+       dev_priv->chipset = chipset;
+       psb_set_uopt(&dev_priv->uopt);
+
+       PSB_DEBUG_GENERAL("Init scheduler\n");
+       psb_scheduler_init(dev, &dev_priv->scheduler);
+
+
+       PSB_DEBUG_INIT("Mapping MMIO\n");
+       resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
+
+       dev_priv->msvdx_reg = ioremap(resource_start + MRST_MSVDX_OFFSET,
+                               PSB_MSVDX_SIZE);
+
+       if (!dev_priv->msvdx_reg)
+               goto out_err;
+
+       dev_priv->topaz_reg = ioremap(resource_start + PNW_TOPAZ_OFFSET,
+                               PNW_TOPAZ_SIZE);
+       if (!dev_priv->topaz_reg)
+               goto out_err;
+
+       dev_priv->vdc_reg =
+               ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE);
+       if (!dev_priv->vdc_reg)
+               goto out_err;
+
+       dev_priv->sgx_reg = ioremap(resource_start + MRST_SGX_OFFSET,
+                               PSB_SGX_SIZE);
+
+       if (!dev_priv->sgx_reg)
+               goto out_err;
+
+       mrst_get_fuse_settings(dev);
+       mrst_get_vbt_data(dev_priv);
+       mid_get_pci_revID(dev_priv);
+
+#ifdef CONFIG_MDFD_GL3
+       // GL3
+       dev_priv->gl3_reg = ioremap(resource_start + MDFLD_GL3_OFFSET,
+                               MDFLD_GL3_SIZE);
+#endif
+
+       PSB_DEBUG_INIT("Init TTM fence and BO driver\n");
+
+       /* Init OSPM support */
+       ospm_power_init(dev);
+
+       ret = psb_ttm_fence_device_init(&dev_priv->fdev);
+       if (unlikely(ret != 0))
+               goto out_err;
+
+       /* For VXD385 DE2.x firmware support 16bit fence value */
+       dev_priv->fdev.fence_class[PSB_ENGINE_VIDEO].wrap_diff = (1 << 14);
+       dev_priv->fdev.fence_class[PSB_ENGINE_VIDEO].flush_diff = (1 << 13);
+       dev_priv->fdev.fence_class[PSB_ENGINE_VIDEO].sequence_mask = 0x0000ffff;
+
+       dev_priv->has_fence_device = 1;
+       ret = ttm_bo_device_init(bdev,
+                                dev_priv->bo_global_ref.ref.object,
+                                &psb_ttm_bo_driver,
+                                DRM_PSB_FILE_PAGE_OFFSET, false);
+       if (unlikely(ret != 0))
+               goto out_err;
+       dev_priv->has_bo_device = 1;
+       ttm_lock_init(&dev_priv->ttm_lock);
+
+       ret = -ENOMEM;
+
+       dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
+       if (!dev_priv->scratch_page)
+               goto out_err;
+
+       set_pages_uc(dev_priv->scratch_page, 1);
+
+       dev_priv->pg = psb_gtt_alloc(dev);
+       if (!dev_priv->pg)
+               goto out_err;
+
+       ret = psb_gtt_init(dev_priv->pg, 0);
+       if (ret)
+               goto out_err;
+
+       ret = psb_gtt_mm_init(dev_priv->pg);
+       if (ret)
+               goto out_err;
+
+       dev_priv->mmu = psb_mmu_driver_init((void *)0,
+                                           drm_psb_trap_pagefaults, 0,
+                                           dev_priv);
+       if (!dev_priv->mmu)
+               goto out_err;
+
+       pg = dev_priv->pg;
+
+       tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+                  (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+       /* CI/RAR use the lower half of TT. */
+       pg->ci_start = (tt_pages / 2) << PAGE_SHIFT;
+       pg->rar_start = pg->ci_start + pg->ci_stolen_size;
+
+
+       /*
+        * Make MSVDX/TOPAZ MMU aware of the CI stolen memory area.
+        */
+       if (dev_priv->pg->ci_stolen_size != 0) {
+               down_read(&pg->sem);
+               ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd
+                                                 (dev_priv->mmu),
+                                                 dev_priv->ci_region_start >> PAGE_SHIFT,
+                                                 pg->mmu_gatt_start + pg->ci_start,
+                                                 pg->ci_stolen_size >> PAGE_SHIFT, 0);
+               up_read(&pg->sem);
+               if (ret)
+                       goto out_err;
+       }
+
+       /*
+        * Make MSVDX/TOPAZ MMU aware of the rar stolen memory area.
+        */
+       if (dev_priv->pg->rar_stolen_size != 0) {
+               down_read(&pg->sem);
+               ret = psb_mmu_insert_pfn_sequence(
+                             psb_mmu_get_default_pd(dev_priv->mmu),
+                             dev_priv->rar_region_start >> PAGE_SHIFT,
+                             pg->mmu_gatt_start + pg->rar_start,
+                             pg->rar_stolen_size >> PAGE_SHIFT, 0);
+               up_read(&pg->sem);
+               if (ret)
+                       goto out_err;
+       }
+
+       dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0);
+       if (!dev_priv->pf_pd)
+               goto out_err;
+
+       psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
+       psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
+
+       spin_lock_init(&dev_priv->sequence_lock);
+
+       PSB_DEBUG_INIT("Begin to init MSVDX/Topaz\n");
+
+       ret = psb_do_init(dev);
+       if (ret)
+               return ret;
+
+       ret = drm_vblank_init(dev, dev_priv->num_pipe);
+       if (ret)
+               goto out_err;
+
+       /*
+        * Install interrupt handlers prior to powering off SGX or else we will
+        * crash.
+        */
+       dev_priv->vdc_irq_mask = 0;
+       dev_priv->pipestat[0] = 0;
+       dev_priv->pipestat[1] = 0;
+       dev_priv->pipestat[2] = 0;
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+       PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
+       PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               drm_irq_install(dev);
+
+       dev->vblank_disable_allowed = 1;
+
+       dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
+       dev->driver->get_vblank_counter = psb_get_vblank_counter;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+       /*init dpu info*/
+       mdfld_dbi_dpu_init(dev);
+#else
+       mdfld_dbi_dsr_init(dev);
+#endif /*CONFIG_MDFLD_DSI_DPU*/
+       INIT_WORK(&dev_priv->te_work, mdfld_te_handler_work);
+
+       /*must be after mrst_get_fuse_settings()*/
+       ret = psb_backlight_init(dev);
+       if (ret)
+               return ret;
+
+       if (drm_psb_no_fb == 0) {
+               psb_modeset_init(dev);
+               psb_fbdev_init(dev);
+               drm_kms_helper_poll_init(dev);
+       }
+
+       /* initialize HDMI Hotplug interrupt forwarding
+       * notifications for user mode
+       */
+
+       /*find handle to drm kboject*/
+       pdev = dev->pdev;
+       ddev = &pdev->dev;
+       kobj = &ddev->kobj;
+
+       dev_priv->psb_hotplug_state = psb_hotplug_init(kobj);
+
+       // GL3
+#ifdef CONFIG_MDFD_GL3
+       if (drm_psb_gl3_enable)
+               gl3_enable();
+#endif
+
+       /*Intel drm driver load is done, continue doing pvr load*/
+       DRM_DEBUG("Pvr driver load\n");
+
+       return PVRSRVDrmLoad(dev, chipset);
+out_err:
+       psb_driver_unload(dev);
+       return ret;
+}
+
+int psb_driver_device_is_agp(struct drm_device *dev)
+{
+       return 0;
+}
+
+int psb_extension_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       union drm_psb_extension_arg *arg = data;
+       struct drm_psb_extension_rep *rep = &arg->rep;
+
+       if (strcmp(arg->extension, "psb_ttm_placement_alphadrop") == 0) {
+               rep->exists = 1;
+               rep->driver_ioctl_offset = DRM_PSB_PLACEMENT_OFFSET;
+               rep->sarea_offset = 0;
+               rep->major = 1;
+               rep->minor = 0;
+               rep->pl = 0;
+               return 0;
+       }
+       if (strcmp(arg->extension, "psb_ttm_fence_alphadrop") == 0) {
+               rep->exists = 1;
+               rep->driver_ioctl_offset = DRM_PSB_FENCE_OFFSET;
+               rep->sarea_offset = 0;
+               rep->major = 1;
+               rep->minor = 0;
+               rep->pl = 0;
+               return 0;
+       }
+       if (strcmp(arg->extension, "psb_ttm_execbuf_alphadrop") == 0) {
+               rep->exists = 1;
+               rep->driver_ioctl_offset = DRM_PSB_CMDBUF;
+               rep->sarea_offset = 0;
+               rep->major = 1;
+               rep->minor = 0;
+               rep->pl = 0;
+               return 0;
+       }
+
+       /*return the page flipping ioctl offset*/
+       if (strcmp(arg->extension, "psb_page_flipping_alphadrop") == 0) {
+               rep->exists = 1;
+               rep->driver_ioctl_offset = DRM_PSB_FLIP;
+               rep->sarea_offset = 0;
+               rep->major = 1;
+               rep->minor = 0;
+               rep->pl = 0;
+               return 0;
+       }
+
+       /* return the video rar offset */
+       if (strcmp(arg->extension, "lnc_video_getparam") == 0) {
+               rep->exists = 1;
+               rep->driver_ioctl_offset = DRM_LNC_VIDEO_GETPARAM;
+               rep->sarea_offset = 0;
+               rep->major = 1;
+               rep->minor = 0;
+               rep->pl = 0;
+               return 0;
+       }
+
+       rep->exists = 0;
+       return 0;
+}
+
+static int psb_vt_leave_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct ttm_bo_device *bdev = &dev_priv->bdev;
+#if 0  /* see REVISIT below */
+       struct ttm_mem_type_manager *man;
+       int clean;
+#endif
+       int ret;
+
+       ret = ttm_vt_lock(&dev_priv->ttm_lock, 1,
+                         psb_fpriv(file_priv)->tfile);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_bo_evict_mm(bdev, TTM_PL_TT);
+       if (unlikely(ret != 0))
+               goto out_unlock;
+
+
+#if 0
+       /*
+        * REVISIT: struct ttm_mem_type_manager no longer has manager field, but
+        * this has not been resolved, because the code only prints an
+        * informational message.
+        */
+       man = &bdev->man[TTM_PL_TT];
+       /*spin_lock(&bdev->lru_lock);*///lru_lock is removed from upstream TTM
+       clean = drm_mm_clean(&man->manager);
+       /*spin_unlock(&bdev->lru_lock);*/
+       if (unlikely(!clean))
+               DRM_INFO("Warning: GATT was not clean after VT switch.\n");
+#endif
+
+       ttm_bo_swapout_all(&dev_priv->bdev);
+
+       return 0;
+out_unlock:
+       (void) ttm_vt_unlock(&dev_priv->ttm_lock);
+       return ret;
+}
+
+static int psb_vt_enter_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       return ttm_vt_unlock(&dev_priv->ttm_lock);
+}
+
+static int psb_sizes_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct drm_psb_sizes_arg *arg =
+               (struct drm_psb_sizes_arg *) data;
+
+       *arg = dev_priv->sizes;
+       return 0;
+}
+
+static int psb_fuse_reg_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       uint32_t *arg = data;
+
+       *arg = dev_priv->fuse_reg_value;
+       return 0;
+}
+static int psb_vbt_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct gct_ioctl_arg *pGCT = data;
+
+       memcpy(pGCT, &dev_priv->gct_data, sizeof(*pGCT));
+
+       return 0;
+}
+
+static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+                             struct drm_file *file_priv)
+{
+       return 0;
+}
+
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       uint32_t *arg = data;
+       dev_priv->blc_adj2 = *arg;
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+       struct backlight_device bd;
+
+       bd.props.brightness = psb_get_brightness(&bd);
+       psb_set_brightness(&bd);
+#endif
+       return 0;
+}
+
+static int psb_adb_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       uint32_t *arg = data;
+       dev_priv->blc_adj1 = *arg;
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+       struct backlight_device bd;
+
+       bd.props.brightness = psb_get_brightness(&bd);
+       psb_set_brightness(&bd);
+#endif
+       return 0;
+}
+
+static int psb_hist_enable_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+{
+       u32 irqCtrl = 0;
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct dpst_guardband guardband_reg;
+       struct dpst_ie_histogram_control ie_hist_cont_reg;
+       uint32_t *enable = data;
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+               return 0;
+       }
+
+       if (*enable == 1) {
+               ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+               ie_hist_cont_reg.ie_pipe_assignment = 0;
+               ie_hist_cont_reg.histogram_mode_select = DPST_YUV_LUMA_MODE;
+               ie_hist_cont_reg.ie_histogram_enable = 1;
+               PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
+
+               guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+               guardband_reg.interrupt_enable = 1;
+               guardband_reg.interrupt_status = 1;
+               PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
+
+               irqCtrl = PSB_RVDC32(PIPEASTAT);
+               PSB_WVDC32(irqCtrl | PIPE_DPST_EVENT_ENABLE, PIPEASTAT);
+               /* Wait for two vblanks */
+       } else {
+               guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+               guardband_reg.interrupt_enable = 0;
+               guardband_reg.interrupt_status = 1;
+               PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
+
+               ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+               ie_hist_cont_reg.ie_histogram_enable = 0;
+               PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
+
+               irqCtrl = PSB_RVDC32(PIPEASTAT);
+               irqCtrl &= ~PIPE_DPST_EVENT_ENABLE;
+               PSB_WVDC32(irqCtrl, PIPEASTAT);
+       }
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       return 0;
+}
+
+static int psb_hist_status_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv                = psb_priv(dev);
+       struct drm_psb_hist_status_arg *hist_status     = data;
+       uint32_t *arg                                   = hist_status->buf;
+       u32 iedbr_reg_data                              = 0;
+       struct dpst_ie_histogram_control ie_hist_cont_reg;
+       u32 i;
+       int dpst3_bin_threshold_count   = 0;
+       uint32_t blm_hist_ctl           = HISTOGRAM_LOGIC_CONTROL;
+       uint32_t iebdr_reg              = HISTOGRAM_BIN_DATA;
+       uint32_t segvalue_max_22_bit    = 0x3fffff;
+       uint32_t iedbr_busy_bit         = 0x80000000;
+       int dpst3_bin_count             = 32;
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               return 0;
+       }
+
+       ie_hist_cont_reg.data                   = PSB_RVDC32(blm_hist_ctl);
+       ie_hist_cont_reg.bin_reg_func_select    = dpst3_bin_threshold_count;
+       ie_hist_cont_reg.bin_reg_index          = 0;
+
+       PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
+
+       for (i = 0; i < dpst3_bin_count; i++) {
+               iedbr_reg_data = PSB_RVDC32(iebdr_reg);
+
+               if (!(iedbr_reg_data & iedbr_busy_bit)) {
+                       arg[i] = iedbr_reg_data & segvalue_max_22_bit;
+               } else {
+                       i = 0;
+                       ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
+                       ie_hist_cont_reg.bin_reg_index = 0;
+                       PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
+               }
+       }
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       return 0;
+}
+
+static int psb_init_comm_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct pci_dev *pdev = NULL;
+       struct device *ddev = NULL;
+       struct kobject *kobj = NULL;
+       uint32_t *arg = data;
+
+       if (*arg == 1) {
+               /*find handle to drm kboject*/
+               pdev = dev->pdev;
+               ddev = &pdev->dev;
+               kobj = &ddev->kobj;
+
+               if (dev_priv->psb_dpst_state == NULL) {
+                       /*init dpst kmum comms*/
+                       dev_priv->psb_dpst_state = psb_dpst_init(kobj);
+               } else {
+                       printk(KERN_ALERT "DPST already initialized\n");
+               }
+
+               psb_irq_enable_dpst(dev);
+               psb_dpst_notify_change_um(DPST_EVENT_INIT_COMPLETE,
+                                         dev_priv->psb_dpst_state);
+       } else {
+               /*hotplug and dpst destroy examples*/
+               psb_irq_disable_dpst(dev);
+               psb_dpst_notify_change_um(DPST_EVENT_TERMINATE,
+                                         dev_priv->psb_dpst_state);
+               psb_dpst_device_pool_destroy(dev_priv->psb_dpst_state);
+               dev_priv->psb_dpst_state = NULL;
+       }
+       return 0;
+}
+
+/* return the current mode to the dpst module */
+static int psb_dpst_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       uint32_t *arg = data;
+       uint32_t x;
+       uint32_t y;
+       uint32_t reg;
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               return 0;
+       }
+
+       reg = PSB_RVDC32(PIPEASRC);
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       /* horizontal is the left 16 bits */
+       x = reg >> 16;
+       /* vertical is the right 16 bits */
+       y = reg & 0x0000ffff;
+
+       /* the values are the image size minus one */
+       x += 1;
+       y += 1;
+
+       *arg = (x << 16) | y;
+
+       return 0;
+}
+static int psb_gamma_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_psb_dpst_lut_arg *lut_arg = data;
+       struct drm_mode_object *obj;
+       struct drm_crtc *crtc;
+       struct drm_connector *connector;
+       struct psb_intel_crtc *psb_intel_crtc;
+       int i = 0;
+       int32_t obj_id;
+
+       obj_id = lut_arg->output_id;
+       obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
+       if (!obj) {
+               DRM_DEBUG("Invalid Connector object.\n");
+               return -EINVAL;
+       }
+
+       connector = obj_to_connector(obj);
+       crtc = connector->encoder->crtc;
+       psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+       for (i = 0; i < 256; i++)
+               psb_intel_crtc->lut_adj[i] = lut_arg->lut[i];
+
+       psb_intel_crtc_load_lut(crtc);
+
+       return 0;
+}
+
+static int psb_update_guard_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct dpst_guardband* input = (struct dpst_guardband*) data;
+       struct dpst_guardband reg_data;
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               return 0;
+       }
+
+       reg_data.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+       reg_data.guardband = input->guardband;
+       reg_data.guardband_interrupt_delay = input->guardband_interrupt_delay;
+       /* printk(KERN_ALERT "guardband = %u\ninterrupt delay = %u\n",
+               reg_data.guardband, reg_data.guardband_interrupt_delay); */
+       PSB_WVDC32(reg_data.data, HISTOGRAM_INT_CONTROL);
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       return 0;
+}
+
+static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv)
+{
+       uint32_t obj_id;
+       uint16_t op;
+       struct drm_mode_modeinfo *umode;
+       struct drm_display_mode *mode = NULL;
+       struct drm_psb_mode_operation_arg *arg;
+       struct drm_mode_object *obj;
+       struct drm_connector *connector;
+       struct drm_framebuffer * drm_fb;
+       struct psb_framebuffer * psb_fb;
+       struct drm_connector_helper_funcs *connector_funcs;
+       int ret = 0;
+       int resp = MODE_OK;
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+
+       arg = (struct drm_psb_mode_operation_arg *)data;
+       obj_id = arg->obj_id;
+       op = arg->operation;
+
+       switch (op) {
+       case PSB_MODE_OPERATION_SET_DC_BASE:
+               obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
+               if (!obj) {
+                       DRM_ERROR("Invalid FB id %d\n", obj_id);
+                       return -EINVAL;
+               }
+
+               drm_fb = obj_to_fb(obj);
+               psb_fb = to_psb_fb(drm_fb);
+
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                             OSPM_UHB_ONLY_IF_ON)) {
+                       REG_WRITE(DSPASURF, psb_fb->offset);
+                       REG_READ(DSPASURF);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               } else {
+                       dev_priv->saveDSPASURF = psb_fb->offset;
+               }
+
+               return 0;
+       case PSB_MODE_OPERATION_MODE_VALID:
+               umode = &arg->mode;
+
+               mutex_lock(&dev->mode_config.mutex);
+
+               obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
+               if (!obj) {
+                       ret = -EINVAL;
+                       goto mode_op_out;
+               }
+
+               connector = obj_to_connector(obj);
+
+               mode = drm_mode_create(dev);
+               if (!mode) {
+                       ret = -ENOMEM;
+                       goto mode_op_out;
+               }
+
+               /* drm_crtc_convert_umode(mode, umode); */
+               {
+                       mode->clock = umode->clock;
+                       mode->hdisplay = umode->hdisplay;
+                       mode->hsync_start = umode->hsync_start;
+                       mode->hsync_end = umode->hsync_end;
+                       mode->htotal = umode->htotal;
+                       mode->hskew = umode->hskew;
+                       mode->vdisplay = umode->vdisplay;
+                       mode->vsync_start = umode->vsync_start;
+                       mode->vsync_end = umode->vsync_end;
+                       mode->vtotal = umode->vtotal;
+                       mode->vscan = umode->vscan;
+                       mode->vrefresh = umode->vrefresh;
+                       mode->flags = umode->flags;
+                       mode->type = umode->type;
+                       strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
+                       mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+               }
+
+               connector_funcs = (struct drm_connector_helper_funcs *)
+                                 connector->helper_private;
+
+               if (connector_funcs->mode_valid) {
+                       resp = connector_funcs->mode_valid(connector, mode);
+                       arg->data = (void *)resp;
+               }
+
+               /*do some clean up work*/
+               if (mode) {
+                       drm_mode_destroy(dev, mode);
+               }
+mode_op_out:
+               mutex_unlock(&dev->mode_config.mutex);
+               return ret;
+
+       default:
+               DRM_DEBUG("Unsupported psb mode operation");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct drm_psb_stolen_memory_arg *arg = data;
+
+       arg->base = dev_priv->pg->stolen_base;
+       arg->size = dev_priv->pg->vram_stolen_size;
+
+       return 0;
+}
+
+static int psb_dpu_query_ioctl(struct drm_device *dev, void *arg,
+                              struct drm_file *file_priv)
+{
+       IMG_INT *data = (IMG_INT*)arg;
+       DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+
+       int panel_type;
+
+       DRM_INFO("dsr query. \n");
+
+       dev_priv->xserver_start = true;
+       panel_type = is_panel_vid_or_cmd(dev);
+
+       if (panel_type == MDFLD_DSI_ENCODER_DPI) {
+               DRM_INFO("DSI panel is working in video mode\n");
+               dev_priv->b_dsr_enable = false;
+               *data = 0;
+               return 0;
+       }
+
+#if defined(CONFIG_MDFLD_DSI_DSR)
+       dev_priv->b_dsr_enable = true;
+       *data = MDFLD_DSR_RR | MDFLD_DSR_FULLSCREEN;
+#elif defined(CONFIG_MDFLD_DSI_DPU)
+       dev_priv->b_dsr_enable = true;
+       *data = MDFLD_DSR_RR | MDFLD_DPU_ENABLE;
+#else /*DBI panel but DSR was not defined*/
+       DRM_INFO("DSR is disabled by kernel configuration.\n");
+
+       dev_priv->b_dsr_enable = false;
+       *data = 0;
+#endif /*CONFIG_MDFLD_DSI_DSR*/
+       return 0;
+}
+
+static int psb_dpu_dsr_on_ioctl(struct drm_device *dev, void *arg,
+                               struct drm_file *file_priv)
+{
+       u32 * param = (u32 *)arg;
+       struct drm_psb_private * dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       int panel_type;
+
+       panel_type = is_panel_vid_or_cmd(dev);
+
+       if (panel_type == MDFLD_DSI_ENCODER_DPI) {
+               DRM_INFO("DSI panel is working in video mode\n");
+               dev_priv->b_dsr_enable = false;
+               return 0;
+       }
+
+       if (!param) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       PSB_DEBUG_ENTRY("dsr kick in. param 0x%08x\n", *param);
+
+       if (*param == DRM_PSB_DSR_DISABLE) {
+               PSB_DEBUG_ENTRY("DSR is turned off\n");
+               dev_priv->b_dsr_enable = false;
+#if defined(CONFIG_MDFLD_DSI_DPU)
+               mdfld_dbi_dpu_report_fullscreen_damage(dev);
+#elif defined(CONFIG_MDFLD_DSI_DSR)
+               mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
+#endif
+               return 0;
+       } else if (*param == DRM_PSB_DSR_ENABLE) {
+               PSB_DEBUG_ENTRY("DSR is turned on\n");
+#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
+               dev_priv->b_dsr_enable = true;
+#endif
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int psb_dpu_dsr_off_ioctl(struct drm_device *dev, void *arg,
+                                struct drm_file *file_priv)
+{
+       static int pipe = 0;
+#if defined(CONFIG_MDFLD_DSI_DPU)
+       struct drm_psb_drv_dsr_off_arg *dsr_off_arg = (struct drm_psb_drv_dsr_off_arg *) arg;
+       struct psb_drm_dpu_rect rect = dsr_off_arg->damage_rect;
+
+       return mdfld_dsi_dbi_dsr_off(dev, &rect);
+#elif defined(CONFIG_MDFLD_DSI_DSR)
+       struct drm_psb_private * dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+
+       pipe++;
+
+       if ((dev_priv->dsr_fb_update & MDFLD_DSR_2D_3D) != MDFLD_DSR_2D_3D) {
+               mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
+       }
+
+       if (pipe > 0) {
+               pipe = 0;
+               if (gdbi_output) {
+                       dev_priv->b_dsr_enable = true;
+                       mdfld_dsi_dbi_enter_dsr(gdbi_output, 1);
+                       mdfld_dsi_dbi_enter_dsr(gdbi_output, 2);
+               }
+       }
+
+#endif
+       return 0;
+}
+
+static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct drm_psb_register_rw_arg *arg = data;
+       unsigned int iep_ble_status;
+       unsigned long iep_timeout;
+       UHBUsage usage =
+               arg->b_force_hw_on ? OSPM_UHB_FORCE_POWER_ON : OSPM_UHB_ONLY_IF_ON;
+
+       if (arg->display_write_mask != 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+                       if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
+                               PSB_WVDC32(arg->display.pfit_controls,
+                                          PFIT_CONTROL);
+                       if (arg->display_write_mask &
+                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+                               PSB_WVDC32(arg->display.pfit_autoscale_ratios,
+                                          PFIT_AUTO_RATIOS);
+                       if (arg->display_write_mask &
+                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+                               PSB_WVDC32(
+                                       arg->display.pfit_programmed_scale_ratios,
+                                       PFIT_PGM_RATIOS);
+                       if (arg->display_write_mask & REGRWBITS_PIPEASRC)
+                               PSB_WVDC32(arg->display.pipeasrc,
+                                          PIPEASRC);
+                       if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
+                               PSB_WVDC32(arg->display.pipebsrc,
+                                          PIPEBSRC);
+                       if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
+                               PSB_WVDC32(arg->display.vtotal_a,
+                                          VTOTAL_A);
+                       if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
+                               PSB_WVDC32(arg->display.vtotal_b,
+                                          VTOTAL_B);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               } else {
+                       if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
+                               dev_priv->savePFIT_CONTROL =
+                                       arg->display.pfit_controls;
+                       if (arg->display_write_mask &
+                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+                               dev_priv->savePFIT_AUTO_RATIOS =
+                                       arg->display.pfit_autoscale_ratios;
+                       if (arg->display_write_mask &
+                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+                               dev_priv->savePFIT_PGM_RATIOS =
+                                       arg->display.pfit_programmed_scale_ratios;
+                       if (arg->display_write_mask & REGRWBITS_PIPEASRC)
+                               dev_priv->savePIPEASRC = arg->display.pipeasrc;
+                       if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
+                               dev_priv->savePIPEBSRC = arg->display.pipebsrc;
+                       if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
+                               dev_priv->saveVTOTAL_A = arg->display.vtotal_a;
+                       if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
+                               dev_priv->saveVTOTAL_B = arg->display.vtotal_b;
+               }
+       }
+
+       if (arg->display_read_mask != 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_CONTROLS)
+                               arg->display.pfit_controls =
+                                       PSB_RVDC32(PFIT_CONTROL);
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+                               arg->display.pfit_autoscale_ratios =
+                                       PSB_RVDC32(PFIT_AUTO_RATIOS);
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+                               arg->display.pfit_programmed_scale_ratios =
+                                       PSB_RVDC32(PFIT_PGM_RATIOS);
+                       if (arg->display_read_mask & REGRWBITS_PIPEASRC)
+                               arg->display.pipeasrc = PSB_RVDC32(PIPEASRC);
+                       if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
+                               arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC);
+                       if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
+                               arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A);
+                       if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
+                               arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               } else {
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_CONTROLS)
+                               arg->display.pfit_controls =
+                                       dev_priv->savePFIT_CONTROL;
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+                               arg->display.pfit_autoscale_ratios =
+                                       dev_priv->savePFIT_AUTO_RATIOS;
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+                               arg->display.pfit_programmed_scale_ratios =
+                                       dev_priv->savePFIT_PGM_RATIOS;
+                       if (arg->display_read_mask & REGRWBITS_PIPEASRC)
+                               arg->display.pipeasrc = dev_priv->savePIPEASRC;
+                       if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
+                               arg->display.pipebsrc = dev_priv->savePIPEBSRC;
+                       if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
+                               arg->display.vtotal_a = dev_priv->saveVTOTAL_A;
+                       if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
+                               arg->display.vtotal_b = dev_priv->saveVTOTAL_B;
+               }
+       }
+
+       if (arg->overlay_write_mask != 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+                       if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
+                               PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5);
+                               PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4);
+                               PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3);
+                               PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2);
+                               PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1);
+                               PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0);
+                       }
+                       if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
+                               PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5);
+                               PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4);
+                               PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3);
+                               PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2);
+                               PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1);
+                               PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0);
+                       }
+
+                       if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) {
+                               PSB_WVDC32(arg->overlay.OVADD, OV_OVADD);
+
+                               if (arg->overlay.b_wait_vblank) {
+                                       /*Wait for 20ms.*/
+                                       unsigned long vblank_timeout = jiffies + HZ / 50;
+                                       uint32_t temp;
+                                       while (time_before_eq(jiffies, vblank_timeout)) {
+                                               temp = PSB_RVDC32(OV_DOVASTA);
+                                               if ((temp & (0x1 << 31)) != 0) {
+                                                       break;
+                                               }
+                                               cpu_relax();
+                                       }
+                               }
+
+                               if ((((arg->overlay.OVADD & OV_PIPE_SELECT) >> OV_PIPE_SELECT_POS) == OV_PIPE_A)) {
+#ifndef CONFIG_MDFLD_DSI_DPU
+                                       mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_OVERLAY_0);
+#else
+                                       /*TODO: report overlay damage*/
+#endif
+                               }
+
+                               if ((((arg->overlay.OVADD & OV_PIPE_SELECT) >> OV_PIPE_SELECT_POS) == OV_PIPE_C)) {
+#ifndef CONFIG_MDFLD_DSI_DPU
+                                       mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_OVERLAY_2);
+#else
+                                       /*TODO: report overlay damage*/
+#endif
+                               }
+
+                               if (arg->overlay.IEP_ENABLED) {
+                                       /* VBLANK period */
+                                       iep_timeout = jiffies + HZ / 10;
+                                       do {
+                                               iep_ble_status = PSB_RVDC32(0x31800);
+                                               if (time_after_eq(jiffies, iep_timeout)) {
+                                                       DRM_ERROR("IEP Lite timeout\n");
+                                                       break;
+                                               }
+                                               cpu_relax();
+                                       } while ((iep_ble_status >> 1) != 1);
+
+                                       arg->overlay.IEP_BLE_MINMAX    = PSB_RVDC32(0x31804);
+                                       arg->overlay.IEP_BSSCC_CONTROL = PSB_RVDC32(0x32000);
+                               }
+                       }
+                       if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) {
+                               PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD);
+                               if (arg->overlay.b_wait_vblank) {
+                                       /*Wait for 20ms.*/
+                                       unsigned long vblank_timeout = jiffies + HZ / 50;
+                                       uint32_t temp;
+                                       while (time_before_eq(jiffies, vblank_timeout)) {
+                                               temp = PSB_RVDC32(OVC_DOVCSTA);
+                                               if ((temp & (0x1 << 31)) != 0) {
+                                                       break;
+                                               }
+                                               cpu_relax();
+                                       }
+                               }
+                       }
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               } else {
+                       if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
+                               dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5;
+                               dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4;
+                               dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3;
+                               dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2;
+                               dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1;
+                               dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0;
+                       }
+                       if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
+                               dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5;
+                               dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4;
+                               dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3;
+                               dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2;
+                               dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1;
+                               dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0;
+                       }
+                       if (arg->overlay_write_mask & OV_REGRWBITS_OVADD)
+                               dev_priv->saveOV_OVADD = arg->overlay.OVADD;
+                       if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD)
+                               dev_priv->saveOVC_OVADD = arg->overlay.OVADD;
+               }
+       }
+
+       if (arg->overlay_read_mask != 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+                       if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
+                               arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+                               arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+                               arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+                               arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+                               arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+                               arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+                       }
+                       if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
+                               arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5);
+                               arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4);
+                               arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3);
+                               arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2);
+                               arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1);
+                               arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0);
+                       }
+                       if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
+                               arg->overlay.OVADD = PSB_RVDC32(OV_OVADD);
+                       if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
+                               arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               } else {
+                       if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
+                               arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5;
+                               arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4;
+                               arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3;
+                               arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2;
+                               arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1;
+                               arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0;
+                       }
+                       if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
+                               arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5;
+                               arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4;
+                               arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3;
+                               arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2;
+                               arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1;
+                               arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0;
+                       }
+                       if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
+                               arg->overlay.OVADD = dev_priv->saveOV_OVADD;
+                       if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
+                               arg->overlay.OVADD = dev_priv->saveOVC_OVADD;
+               }
+       }
+
+       if (arg->sprite_enable_mask != 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+                       PSB_WVDC32(0x1F3E, DSPARB);
+                       PSB_WVDC32(arg->sprite.dspa_control | PSB_RVDC32(DSPACNTR), DSPACNTR);
+                       PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL);
+                       PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK);
+                       PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF);
+                       PSB_RVDC32(DSPASURF);
+                       PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR);
+                       PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE);
+                       PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS);
+                       PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF);
+                       PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE);
+                       PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
+                       PSB_RVDC32(DSPCSURF);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               }
+       }
+
+       if (arg->sprite_disable_mask != 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+                       PSB_WVDC32(0x3F3E, DSPARB);
+                       PSB_WVDC32(0x0, DSPCCNTR);
+                       PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
+                       PSB_RVDC32(DSPCSURF);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               }
+       }
+
+       if (arg->subpicture_enable_mask != 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+                       uint32_t temp;
+                       if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) {
+                               temp =  PSB_RVDC32(DSPACNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp &= ~DISPPLANE_BOTTOM;
+                               temp |= DISPPLANE_32BPP;
+                               PSB_WVDC32(temp, DSPACNTR);
+
+                               temp =  PSB_RVDC32(DSPABASE);
+                               PSB_WVDC32(temp, DSPABASE);
+                               PSB_RVDC32(DSPABASE);
+                               temp =  PSB_RVDC32(DSPASURF);
+                               PSB_WVDC32(temp, DSPASURF);
+                               PSB_RVDC32(DSPASURF);
+                       }
+                       if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) {
+                               temp =  PSB_RVDC32(DSPBCNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp &= ~DISPPLANE_BOTTOM;
+                               temp |= DISPPLANE_32BPP;
+                               PSB_WVDC32(temp, DSPBCNTR);
+
+                               temp =  PSB_RVDC32(DSPBBASE);
+                               PSB_WVDC32(temp, DSPBBASE);
+                               PSB_RVDC32(DSPBBASE);
+                               temp =  PSB_RVDC32(DSPBSURF);
+                               PSB_WVDC32(temp, DSPBSURF);
+                               PSB_RVDC32(DSPBSURF);
+                       }
+                       if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) {
+                               temp =  PSB_RVDC32(DSPCCNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp &= ~DISPPLANE_BOTTOM;
+                               temp |= DISPPLANE_32BPP;
+                               PSB_WVDC32(temp, DSPCCNTR);
+
+                               temp =  PSB_RVDC32(DSPCBASE);
+                               PSB_WVDC32(temp, DSPCBASE);
+                               PSB_RVDC32(DSPCBASE);
+                               temp =  PSB_RVDC32(DSPCSURF);
+                               PSB_WVDC32(temp, DSPCSURF);
+                               PSB_RVDC32(DSPCSURF);
+                       }
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               }
+       }
+
+       if (arg->subpicture_disable_mask != 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+                       uint32_t temp;
+                       if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) {
+                               temp =  PSB_RVDC32(DSPACNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp |= DISPPLANE_32BPP_NO_ALPHA;
+                               PSB_WVDC32(temp, DSPACNTR);
+
+                               temp =  PSB_RVDC32(DSPABASE);
+                               PSB_WVDC32(temp, DSPABASE);
+                               PSB_RVDC32(DSPABASE);
+                               temp =  PSB_RVDC32(DSPASURF);
+                               PSB_WVDC32(temp, DSPASURF);
+                               PSB_RVDC32(DSPASURF);
+                       }
+                       if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) {
+                               temp =  PSB_RVDC32(DSPBCNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp |= DISPPLANE_32BPP_NO_ALPHA;
+                               PSB_WVDC32(temp, DSPBCNTR);
+
+                               temp =  PSB_RVDC32(DSPBBASE);
+                               PSB_WVDC32(temp, DSPBBASE);
+                               PSB_RVDC32(DSPBBASE);
+                               temp =  PSB_RVDC32(DSPBSURF);
+                               PSB_WVDC32(temp, DSPBSURF);
+                               PSB_RVDC32(DSPBSURF);
+                       }
+                       if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) {
+                               temp =  PSB_RVDC32(DSPCCNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp |= DISPPLANE_32BPP_NO_ALPHA;
+                               PSB_WVDC32(temp, DSPCCNTR);
+
+                               temp =  PSB_RVDC32(DSPCBASE);
+                               PSB_WVDC32(temp, DSPCBASE);
+                               PSB_RVDC32(DSPCBASE);
+                               temp =  PSB_RVDC32(DSPCSURF);
+                               PSB_WVDC32(temp, DSPCSURF);
+                               PSB_RVDC32(DSPCSURF);
+                       }
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               }
+       }
+
+       return 0;
+}
+
+static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
+{
+       DRM_DEBUG("\n");
+       return PVRSRVOpen(dev, priv);
+}
+
+static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
+                              unsigned long arg)
+{
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->minor->dev;
+       unsigned int nr = DRM_IOCTL_NR(cmd);
+       long ret;
+
+       DRM_DEBUG("cmd = %x, nr = %x\n", cmd, nr);
+
+       /*
+        * The driver private ioctls and TTM ioctls should be
+        * thread-safe.
+        */
+
+       if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
+           && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+               struct drm_ioctl_desc *ioctl =
+                                       &psb_ioctls[nr - DRM_COMMAND_BASE];
+
+               if (unlikely(ioctl->cmd != cmd)) {
+                       DRM_ERROR(
+                               "Invalid drm cmnd %d ioctl->cmd %x, cmd %x\n",
+                               nr - DRM_COMMAND_BASE, ioctl->cmd, cmd);
+                       return -EINVAL;
+               }
+       }
+       /*
+        * Not all old drm ioctls are thread-safe.
+        */
+
+       /* FIXME: lock_kernel(); */
+       ret = drm_ioctl(filp, cmd, arg);
+       /* FIXME: unlock_kernel(); */
+       return ret;
+}
+
+static int psb_blc_proc_show(struct seq_file *seq, void *v)
+{
+       struct drm_minor *minor = (struct drm_minor *) seq->private;
+       struct drm_device *dev = minor->dev;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       int user_brightness = 0;
+       int final_brightness = 0;
+
+       user_brightness = psb_get_brightness(NULL);
+       final_brightness = (user_brightness * dev_priv->blc_adj1) / 100;
+       final_brightness = (final_brightness * dev_priv->blc_adj2) / 100;
+
+       DRM_INFO("%i\n", final_brightness);
+       seq_printf(seq, "%i\n", final_brightness);
+
+       return 0;
+}
+
+static int psb_blc_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, psb_blc_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations psb_blc_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = psb_blc_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int psb_rtpm_read(char *buf, char **start, off_t offset, int request,
+                        int *eof, void *data)
+{
+       printk(KERN_ALERT "Current Runtime PM delay for GFX: %d (ms) \n", gfxrtdelay);
+
+       return 0;
+}
+
+static int psb_rtpm_write(struct file *file, const char *buffer,
+                         unsigned long count, void *data)
+{
+       char buf[2];
+       int temp = 0;
+       if (count != sizeof(buf)) {
+               return -EINVAL;
+       } else {
+               if (copy_from_user(buf, buffer, count))
+                       return -EINVAL;
+               if (buf[count-1] != '\n')
+                       return -EINVAL;
+               temp = buf[0] - '0';
+               switch (temp) {
+               case 1:
+                       gfxrtdelay = 10 * 1000;
+                       break;
+
+               case 2:
+                       gfxrtdelay = 20 * 1000;
+                       break;
+               default:
+                       gfxrtdelay = 30 * 1000;
+                       break;
+               }
+               printk(KERN_ALERT "Runtime PM delay set for GFX: %d (ms) \n", gfxrtdelay);
+       }
+       return count;
+}
+
+static int psb_ospm_read(char *buf, char **start, off_t offset, int request,
+                        int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       int len = 0;
+#ifdef OSPM_STAT
+       unsigned long on_time = 0;
+       unsigned long off_time = 0;
+#endif
+
+       *start = &buf[offset];
+       *eof = 0;
+
+       /*#ifdef SUPPORT_ACTIVE_POWER_MANAGEMENT
+           DRM_INFO("GFX D0i3: enabled       ");
+       #else
+           DRM_INFO("GFX D0i3: disabled              ");
+       #endif*/
+       if (drm_psb_ospm)
+               DRM_INFO("GFX D0i3: enabled           ");
+       else
+               DRM_INFO("GFX D0i3: disabled          ");
+
+#ifdef OSPM_STAT
+       switch (dev_priv->graphics_state) {
+       case PSB_PWR_STATE_ON:
+               DRM_INFO("GFX state:%s\n", "on");
+               break;
+       case PSB_PWR_STATE_OFF:
+               DRM_INFO("GFX state:%s\n", "off");
+               break;
+       default:
+               DRM_INFO("GFX state:%s\n", "unknown");
+       }
+
+       on_time = dev_priv->gfx_on_time * 1000 / HZ;
+       off_time = dev_priv->gfx_off_time * 1000 / HZ;
+       switch (dev_priv->graphics_state) {
+       case PSB_PWR_STATE_ON:
+               on_time += (jiffies - dev_priv->gfx_last_mode_change) * \
+                          1000 / HZ;
+               break;
+       case PSB_PWR_STATE_OFF:
+               off_time += (jiffies - dev_priv->gfx_last_mode_change) * \
+                           1000 / HZ;
+               break;
+       }
+       DRM_INFO("GFX(count/ms):\n");
+       DRM_INFO("on:%lu/%lu, off:%lu/%lu \n",
+                dev_priv->gfx_on_cnt, on_time, dev_priv->gfx_off_cnt, off_time);
+#endif
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+
+static int psb_ospm_write(struct file *file, const char *buffer,
+                         unsigned long count, void *data)
+{
+       char buf[2];
+       if (count != sizeof(buf)) {
+               return -EINVAL;
+       } else {
+               if (copy_from_user(buf, buffer, count))
+                       return -EINVAL;
+               if (buf[count-1] != '\n')
+                       return -EINVAL;
+               drm_psb_ospm = buf[0] - '0';
+               printk(KERN_ALERT " SGX (D0i3) drm_psb_ospm: %d \n",
+                      drm_psb_ospm);
+               /*Work around for video encode, it needs sgx always on*/
+               if (!drm_psb_ospm) {
+                       ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true);
+                       ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+               }
+       }
+       return count;
+}
+
+/*
+* use to read and write display register. and print to standard output.
+*/
+static int psb_display_register_write(struct file *file, const char *buffer,
+                                     unsigned long count, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       int reg_val = 0;
+       char buf[255];
+       char op = '0';
+       int  reg = 0;
+       int  val = 0;
+       int  counter = 0;
+
+       memset(buf, '\0', sizeof(buf));
+
+       if (count > sizeof(buf)) {
+               printk(KERN_ALERT "The input is too bigger, kernel can not handle.\n");
+               return -EINVAL;
+       } else {
+               if (copy_from_user(buf, buffer, count))
+                       return -EINVAL;
+               if (buf[count-1] != '\n')
+                       return -EINVAL;
+               printk(KERN_ALERT "input = %s", buf);
+       }
+
+       sscanf(buf, "%c%x%x", &op, &reg, &val);
+
+       if (op != 'r' && op != 'w') {
+               printk(KERN_ALERT "The input format is not right!\n");
+               printk(KERN_ALERT "for exampe: r 70184 10 - where 10 is number of dwords\n");
+               printk(KERN_ALERT "for exampe: w 70184 123\n");
+               return -EINVAL;
+       }
+       if (reg < 0xa000 || reg >  0x720ff) {
+               printk(KERN_ALERT "the register is out of display controller registers rang.\n");
+               return -EINVAL;
+       }
+
+       if ((reg % 0x4) != 0) {
+               printk(KERN_ALERT "the register address should aligned to 4 byte.please refrence display controller specification.\n");
+               return -EINVAL;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                      OSPM_UHB_FORCE_POWER_ON)) {
+               printk(KERN_ALERT "Display controller can not power on.!\n");
+               return -EPERM;
+       }
+#ifndef CONFIG_MDFLD_DSI_DPU
+       mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0); //assume cursor move once
+#endif
+       if (op == 'r') {
+               if (!val)
+                       val = 1;
+
+               for (counter = 0; counter < val; counter++) {
+                       reg_val = REG_READ(reg);
+                       printk(KERN_ALERT "Read :reg=0x%08x , val=0x%08x.\n", reg, reg_val);
+                       reg = reg + 4;
+               }
+       }
+       if (op == 'w') {
+               reg_val = REG_READ(reg);
+               printk(KERN_ALERT "Before change:reg=0x%08x , val=0x%08x.\n", reg, reg_val);
+
+               REG_WRITE(reg, val);
+
+               reg_val = ioread32(dev_priv->vdc_reg + (reg));
+               printk(KERN_ALERT "After change:reg=0x%08x , val=0x%08x.\n", reg, reg_val);
+       }
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       return count;
+}
+
+/* When a client dies:
+ *    - Check for and clean up flipped page state
+ */
+void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
+{
+}
+
+static void psb_remove(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       drm_put_dev(dev);
+}
+
+#if 0
+static int psb_proc_init(struct drm_minor *minor)
+{
+       struct proc_dir_entry *ent;
+       struct proc_dir_entry *ent1;
+       struct proc_dir_entry *rtpm;
+       struct proc_dir_entry *ent_display_status;
+
+       /* register proc entry for ospm */
+       ent = create_proc_entry(OSPM_PROC_ENTRY, 0644, minor->proc_root);
+       if (ent) {
+               ent->read_proc = psb_ospm_read;
+               ent->write_proc = psb_ospm_write;
+               ent->data = (void *)minor;
+       } else {
+                printk(KERN_ALERT "GFX: Create Proc Entry for OSPM Failed.\n");
+       }
+
+       /* register proc entry for runtime PM */
+        rtpm = create_proc_entry(RTPM_PROC_ENTRY, 0644, minor->proc_root);
+       if (rtpm) {
+               rtpm->read_proc = psb_rtpm_read;
+               rtpm->write_proc = psb_rtpm_write;
+       } else {
+                printk(KERN_ALERT "GFX: Create Proc Entry for Runtime PM Failed.\n");
+       }
+
+       /* register proc entry for display register read/write */
+        ent_display_status = create_proc_entry(DISPLAY_PROC_ENTRY, 0644, minor->proc_root);
+       if (ent_display_status) {
+               ent_display_status->write_proc = psb_display_register_write;
+               ent_display_status->data = (void *)minor;
+       } else {
+                printk(KERN_ALERT "GFX: Create Proc Entry for Display Status Failed.\n");
+       }
+
+       /* register proc data for backlight */
+        ent1 = proc_create_data(BLC_PROC_ENTRY, 0, minor->proc_root, &psb_blc_proc_fops, minor);
+       if (!ent1) {
+                printk(KERN_ALERT "GFX: Create Proc Data for Backlight Failed.\n");
+       }
+
+       return 0;
+}
+
+static void psb_proc_cleanup(struct drm_minor *minor)
+{
+       remove_proc_entry(OSPM_PROC_ENTRY, minor->proc_root);
+       remove_proc_entry(RTPM_PROC_ENTRY, minor->proc_root);
+       remove_proc_entry(BLC_PROC_ENTRY, minor->proc_root);
+        remove_proc_entry(DISPLAY_PROC_ENTRY, minor->proc_root);
+       return;
+}
+#endif
+
+static const struct dev_pm_ops psb_pm_ops = {
+       .runtime_suspend = psb_runtime_suspend,
+       .runtime_resume = psb_runtime_resume,
+       .runtime_idle = psb_runtime_idle,
+};
+
+static struct drm_driver driver = {
+       .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
+       DRIVER_IRQ_VBL | DRIVER_MODESET,
+       .load = psb_driver_load,
+       .unload = psb_driver_unload,
+
+       .ioctls = psb_ioctls,
+       .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
+       .device_is_agp = psb_driver_device_is_agp,
+       .irq_preinstall = psb_irq_preinstall,
+       .irq_postinstall = psb_irq_postinstall,
+       .irq_uninstall = psb_irq_uninstall,
+       .irq_handler = psb_irq_handler,
+       .enable_vblank = psb_enable_vblank,
+       .disable_vblank = psb_disable_vblank,
+       .get_vblank_counter = psb_get_vblank_counter,
+       .firstopen = NULL,
+       .lastclose = psb_lastclose,
+       .open = psb_driver_open,
+       .postclose = PVRSRVDrmPostClose,
+       .suspend = PVRSRVDriverSuspend,
+       .resume = PVRSRVDriverResume,
+       .preclose = psb_driver_preclose,
+       .fops = {
+               .owner = THIS_MODULE,
+               .open = psb_open,
+               .release = psb_release,
+               .unlocked_ioctl = psb_unlocked_ioctl,
+               .mmap = psb_mmap,
+               .poll = drm_poll,
+               .fasync = drm_fasync,
+               .read = drm_read,
+       },
+       .name = DRIVER_NAME,
+        .desc = DRIVER_DESC,
+         .date = PSB_DRM_DRIVER_DATE,
+          .major = PSB_DRM_DRIVER_MAJOR,
+           .minor = PSB_DRM_DRIVER_MINOR,
+            .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
+                  };
+
+static struct pci_driver psb_pci_driver = {
+       .name = DRIVER_NAME,
+       .id_table = pciidlist,
+       .resume = ospm_power_resume,
+       .suspend = ospm_power_suspend,
+       .probe = psb_probe,
+       .remove = psb_remove,
+#ifdef CONFIG_PM
+       .driver.pm = &psb_pm_ops,
+#endif
+};
+
+static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       if (pci_enable_msi(pdev))
+               DRM_ERROR("Enable MSI failed!\n");
+       return drm_get_pci_dev(pdev, ent, &driver);
+}
+
+#ifndef MODULE
+static __init int parse_panelid(char *arg)
+{
+       /* panel ID can be passed in as a cmdline parameter */
+       /* to enable this feature add panelid=TMD to cmdline for TMD panel*/
+       if (!arg)
+               return -EINVAL;
+
+       if (!strcasecmp(arg, "TMD_CMD"))
+               PanelID = TMD_CMD;
+       else if (!strcasecmp(arg, "TPO_CMD"))
+               PanelID = TPO_CMD;
+       else if (!strcasecmp(arg, "TMD_VID"))
+               PanelID = TMD_VID;
+       else if (!strcasecmp(arg, "TPO_VID"))
+               PanelID = TPO_VID;
+       else if (!strcasecmp(arg, "TC35876X"))
+               PanelID = TC35876X;
+       else
+               PanelID = GCT_DETECT;
+
+       return 0;
+}
+early_param("panelid", parse_panelid);
+#endif
+
+#ifndef MODULE
+static __init int parse_hdmi_edid(char *arg)
+{
+       /* HDMI EDID info can be passed in as a cmdline parameter,
+        * and need to remove it after we can get EDID info via MSIC.*/
+       if ((!arg) || (strlen(arg) >= 20))
+               return -EINVAL;
+
+       strcpy(HDMI_EDID, arg);
+
+       return 0;
+}
+early_param("hdmi_edid", parse_hdmi_edid);
+#endif
+
+static int __init psb_init(void)
+{
+       int ret;
+
+#if defined(MODULE) && defined(CONFIG_NET)
+       psb_kobject_uevent_init();
+#endif
+
+       ret = SYSPVRInit();
+       if (ret != 0) {
+               return ret;
+       }
+
+       ret = drm_pci_init(&driver, &psb_pci_driver);
+       if (ret != 0) {
+               return ret;
+       }
+
+       /*init for bc_video*/
+       ret = BC_Video_ModInit();
+       if (ret != 0) {
+               return ret;
+       }
+
+#ifdef CONFIG_MDFD_HDMI
+       msic_regsiter_driver();
+#endif
+
+       return ret;
+}
+
+static void __exit psb_exit(void)
+{
+       int ret;
+       /*cleanup for bc_video*/
+       ret = BC_Video_ModCleanup();
+       if (ret != 0) {
+               return;
+       }
+#ifdef CONFIG_MDFD_HDMI
+       msic_unregister_driver();
+#endif
+       drm_pci_exit(&driver, &psb_pci_driver);
+}
+
+late_initcall(psb_init);
+module_exit(psb_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/mrst/drv/psb_drv.h b/drivers/staging/mrst/drv/psb_drv.h
new file mode 100644 (file)
index 0000000..4b9e580
--- /dev/null
@@ -0,0 +1,1351 @@
+/**************************************************************************
+ * Copyright (c) 2007-2008, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRV_H_
+#define _PSB_DRV_H_
+
+#include <linux/version.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_global.h>
+#include "sys_pvr_drm_export.h"
+#include "psb_drm.h"
+#include "psb_reg.h"
+#include "psb_schedule.h"
+#include "psb_intel_drv.h"
+#include "psb_hotplug.h"
+#include "psb_dpst.h"
+#include "psb_gtt.h"
+#include "psb_powermgmt.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_driver.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_lock.h"
+#include "psb_irq.h"
+
+/*IMG headers*/
+#include "private_data.h"
+#include "pvr_drm.h"
+
+#include "mdfld_hdmi_audio_if.h"
+
+/*Append new drm mode definition here, align with libdrm definition*/
+#define DRM_MODE_SCALE_NO_SCALE   2
+
+extern struct ttm_bo_driver psb_ttm_bo_driver;
+
+enum {
+       CHIP_PSB_8108 = 0,
+       CHIP_PSB_8109 = 1,
+       CHIP_MRST_4100 = 2,
+       CHIP_MDFLD_0130 = 3
+};
+
+enum panel_type {
+       TPO_CMD,
+       TPO_VID,
+       TMD_CMD,
+       TMD_VID,
+       TPO,
+       TMD,
+       HDMI,
+       TC35876X,
+       GCT_DETECT
+};
+
+#define PCI_ID_TOPAZ_DISABLED 0x4101
+
+/*
+ *Hardware bugfixes
+ */
+
+#define FIX_TG_16
+#define FIX_TG_2D_CLOCKGATE
+#define OSPM_STAT
+
+#define DRIVER_NAME "pvrsrvkm"
+#define DRIVER_DESC "drm driver for the Intel GMA500"
+#define DRIVER_AUTHOR "Intel Corporation"
+#define OSPM_PROC_ENTRY "ospm"
+#define RTPM_PROC_ENTRY "rtpm"
+#define BLC_PROC_ENTRY "mrst_blc"
+#define DISPLAY_PROC_ENTRY "display_status"
+
+#define PSB_DRM_DRIVER_DATE "2009-03-10"
+#define PSB_DRM_DRIVER_MAJOR 8
+#define PSB_DRM_DRIVER_MINOR 1
+#define PSB_DRM_DRIVER_PATCHLEVEL 0
+
+/*
+ *TTM driver private offsets.
+ */
+
+#define DRM_PSB_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+#define PSB_OBJECT_HASH_ORDER 13
+#define PSB_FILE_OBJECT_HASH_ORDER 12
+#define PSB_BO_HASH_ORDER 12
+
+#define PSB_VDC_OFFSET          0x00000000
+#define PSB_VDC_SIZE            0x000080000
+#define MRST_MMIO_SIZE          0x0000C0000
+#define MDFLD_MMIO_SIZE          0x000100000
+#define PSB_SGX_SIZE            0x8000
+#define PSB_SGX_OFFSET          0x00040000
+#ifdef CONFIG_MDFD_GL3
+#define MDFLD_GL3_OFFSET        0x00000000
+#define MDFLD_GL3_SIZE          0x00040000
+#endif
+#define MRST_SGX_OFFSET                 0x00080000
+#define PSB_MMIO_RESOURCE       0
+#define PSB_GATT_RESOURCE       2
+#define PSB_GTT_RESOURCE        3
+#define PSB_GMCH_CTRL           0x52
+#define PSB_BSM                         0x5C
+#define _PSB_GMCH_ENABLED       0x4
+#define PSB_PGETBL_CTL          0x2020
+#define _PSB_PGETBL_ENABLED     0x00000001
+#define PSB_SGX_2D_SLAVE_PORT   0x4000
+#define PSB_TT_PRIV0_LIMIT      (256*1024*1024)
+#define PSB_TT_PRIV0_PLIMIT     (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
+#define PSB_NUM_VALIDATE_BUFFERS 2048
+
+#define PSB_MEM_MMU_START       0x00000000
+#define PSB_MEM_TT_START        0xE0000000
+
+#define PSB_GL3_CACHE_CTL      0x2100
+#define PSB_GL3_CACHE_STAT     0x2108
+
+/*
+ *Flags for external memory type field.
+ */
+
+#define MRST_MSVDX_OFFSET      0x90000 /*MSVDX Base offset */
+#define PSB_MSVDX_OFFSET       0x50000 /*MSVDX Base offset */
+/* MSVDX MMIO region is 0x50000 - 0x57fff ==> 32KB */
+#define PSB_MSVDX_SIZE         0x10000
+
+#define LNC_TOPAZ_OFFSET       0xA0000
+#define PNW_TOPAZ_OFFSET       0xC0000
+#define PNW_GL3_OFFSET         0xB0000
+#define LNC_TOPAZ_SIZE         0x10000
+#define PNW_TOPAZ_SIZE         0x30000 /* PNW VXE285 has two cores */
+#define PSB_MMU_CACHED_MEMORY    0x0001        /* Bind to MMU only */
+#define PSB_MMU_RO_MEMORY        0x0002        /* MMU RO memory */
+#define PSB_MMU_WO_MEMORY        0x0004        /* MMU WO memory */
+
+/*
+ *PTE's and PDE's
+ */
+
+#define PSB_PDE_MASK             0x003FFFFF
+#define PSB_PDE_SHIFT            22
+#define PSB_PTE_SHIFT            12
+
+#define PSB_PTE_VALID            0x0001        /* PTE / PDE valid */
+#define PSB_PTE_WO               0x0002        /* Write only */
+#define PSB_PTE_RO               0x0004        /* Read only */
+#define PSB_PTE_CACHED           0x0008        /* CPU cache coherent */
+
+/*
+ *VDC registers and bits
+ */
+#define PSB_MSVDX_CLOCKGATING    0x2064
+#define PSB_TOPAZ_CLOCKGATING    0x2068
+#define PSB_HWSTAM               0x2098
+#define PSB_INSTPM               0x20C0
+#define PSB_INT_IDENTITY_R        0x20A4
+#define _MDFLD_PIPEC_EVENT_FLAG   (1<<2)
+#define _MDFLD_PIPEC_VBLANK_FLAG  (1<<3)
+#define _PSB_DPST_PIPEB_FLAG      (1<<4)
+#define _MDFLD_PIPEB_EVENT_FLAG   (1<<4)
+#define _PSB_VSYNC_PIPEB_FLAG    (1<<5)
+#define _PSB_DPST_PIPEA_FLAG      (1<<6)
+#define _PSB_PIPEA_EVENT_FLAG     (1<<6)
+#define _PSB_VSYNC_PIPEA_FLAG    (1<<7)
+#define _MDFLD_MIPIA_FLAG        (1<<16)
+#define _MDFLD_MIPIC_FLAG        (1<<17)
+#define _PSB_IRQ_SGX_FLAG        (1<<18)
+#define _PSB_IRQ_MSVDX_FLAG      (1<<19)
+#define _LNC_IRQ_TOPAZ_FLAG      (1<<20)
+#ifdef CONFIG_MDFD_GL3
+#define _MDFLD_GL3_IRQ_FLAG      (1<<21)
+#define _MDFLD_GL3_ECC_FLAG      (1<<2)  /* unrecoverable ecc error.  We must flush and reset */
+#endif
+
+/* This flag includes all the display IRQ bits excepts the vblank irqs. */
+#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | _MDFLD_PIPEB_EVENT_FLAG | \
+        _PSB_PIPEA_EVENT_FLAG | _PSB_VSYNC_PIPEA_FLAG | _MDFLD_MIPIA_FLAG | _MDFLD_MIPIC_FLAG)
+#define PSB_INT_IDENTITY_R       0x20A4
+#define PSB_INT_MASK_R           0x20A8
+#define PSB_INT_ENABLE_R         0x20A0
+
+#define _PSB_MMU_ER_MASK      0x0001FF00
+#define _PSB_MMU_ER_HOST      (1 << 16)
+#define GPIOA                  0x5010
+#define GPIOB                  0x5014
+#define GPIOC                  0x5018
+#define GPIOD                  0x501c
+#define GPIOE                  0x5020
+#define GPIOF                  0x5024
+#define GPIOG                  0x5028
+#define GPIOH                  0x502c
+#define GPIO_CLOCK_DIR_MASK            (1 << 0)
+#define GPIO_CLOCK_DIR_IN              (0 << 1)
+#define GPIO_CLOCK_DIR_OUT             (1 << 1)
+#define GPIO_CLOCK_VAL_MASK            (1 << 2)
+#define GPIO_CLOCK_VAL_OUT             (1 << 3)
+#define GPIO_CLOCK_VAL_IN              (1 << 4)
+#define GPIO_CLOCK_PULLUP_DISABLE      (1 << 5)
+#define GPIO_DATA_DIR_MASK             (1 << 8)
+#define GPIO_DATA_DIR_IN               (0 << 9)
+#define GPIO_DATA_DIR_OUT              (1 << 9)
+#define GPIO_DATA_VAL_MASK             (1 << 10)
+#define GPIO_DATA_VAL_OUT              (1 << 11)
+#define GPIO_DATA_VAL_IN               (1 << 12)
+#define GPIO_DATA_PULLUP_DISABLE       (1 << 13)
+
+#define VCLK_DIVISOR_VGA0   0x6000
+#define VCLK_DIVISOR_VGA1   0x6004
+#define VCLK_POST_DIV      0x6010
+
+#define PSB_COMM_2D (PSB_ENGINE_2D << 4)
+#define PSB_COMM_3D (PSB_ENGINE_3D << 4)
+#define PSB_COMM_TA (PSB_ENGINE_TA << 4)
+#define PSB_COMM_HP (PSB_ENGINE_HP << 4)
+#define PSB_COMM_USER_IRQ (1024 >> 2)
+#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1)
+#define PSB_COMM_FW (2048 >> 2)
+
+#define PSB_UIRQ_VISTEST              1
+#define PSB_UIRQ_OOM_REPLY            2
+#define PSB_UIRQ_FIRE_TA_REPLY        3
+#define PSB_UIRQ_FIRE_RASTER_REPLY     4
+
+#define PSB_2D_SIZE (256*1024*1024)
+#define PSB_MAX_RELOC_PAGES 1024
+
+#define PSB_LOW_REG_OFFS 0x0204
+#define PSB_HIGH_REG_OFFS 0x0600
+
+#define PSB_NUM_VBLANKS 2
+
+
+#define PSB_2D_SIZE (256*1024*1024)
+#define PSB_MAX_RELOC_PAGES 1024
+
+#define PSB_LOW_REG_OFFS 0x0204
+#define PSB_HIGH_REG_OFFS 0x0600
+
+#define PSB_NUM_VBLANKS 2
+#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
+#define PSB_LID_DELAY (DRM_HZ / 10)
+
+#define MDFLD_PNW_A0 0x00
+#define MDFLD_PNW_B0 0x04
+#define MDFLD_PNW_C0 0x08
+
+#define MDFLD_DSR_2D_3D_0      BIT(0)
+#define MDFLD_DSR_2D_3D_2      BIT(1)
+#define MDFLD_DSR_CURSOR_0     BIT(2)
+#define MDFLD_DSR_CURSOR_2     BIT(3)
+#define MDFLD_DSR_OVERLAY_0    BIT(4)
+#define MDFLD_DSR_OVERLAY_2    BIT(5)
+#define MDFLD_DSR_MIPI_CONTROL BIT(6)
+#define MDFLD_DSR_DAMAGE_MASK_0        (BIT(0) | BIT(2) | BIT(4))
+#define MDFLD_DSR_DAMAGE_MASK_2        (BIT(1) | BIT(3) | BIT(5))
+#define MDFLD_DSR_2D_3D        (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
+
+#define MDFLD_DSR_RR 45 
+#define MDFLD_DPU_ENABLE BIT(31)
+#define MDFLD_DSR_FULLSCREEN BIT(30)
+#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR)
+
+#define PSB_PWR_STATE_ON               1
+#define PSB_PWR_STATE_OFF              2
+
+#define PSB_PMPOLICY_NOPM              0
+#define PSB_PMPOLICY_CLOCKGATING       1
+#define PSB_PMPOLICY_POWERDOWN         2
+
+#define PSB_PMSTATE_POWERUP            0
+#define PSB_PMSTATE_CLOCKGATED         1
+#define PSB_PMSTATE_POWERDOWN          2
+#define PSB_PCIx_MSI_ADDR_LOC          0x94
+#define PSB_PCIx_MSI_DATA_LOC          0x98
+
+#define MDFLD_PLANE_MAX_WIDTH          2048
+#define MDFLD_PLANE_MAX_HEIGHT         2048
+
+/*
+ *User options.
+ */
+
+struct drm_psb_uopt {
+       int pad; /*keep it here in case we use it in future*/
+};
+
+/**
+ *struct psb_context
+ *
+ *@buffers:     array of pre-allocated validate buffers.
+ *@used_buffers: number of buffers in @buffers array currently in use.
+ *@validate_buffer: buffers validated from user-space.
+ *@kern_validate_buffers : buffers validated from kernel-space.
+ *@fence_flags : Fence flags to be used for fence creation.
+ *
+ *This structure is used during execbuf validation.
+ */
+
+struct psb_context {
+       struct psb_validate_buffer *buffers;
+       uint32_t used_buffers;
+       struct list_head validate_list;
+       struct list_head kern_validate_list;
+       uint32_t fence_types;
+};
+
+struct psb_validate_buffer;
+
+struct psb_msvdx_cmd_queue {
+       struct list_head head;
+       void *cmd;
+       unsigned long cmd_size;
+       uint32_t sequence;
+};
+
+/* Currently defined entrypoints */
+enum VAEntrypoint {
+       VAEntrypointVLD         = 1,
+       VAEntrypointIZZ         = 2,
+       VAEntrypointIDCT        = 3,
+       VAEntrypointMoComp      = 4,
+       VAEntrypointDeblocking  = 5,
+       VAEntrypointEncSlice    = 6,    /* slice level encode */
+       VAEntrypointEncPicture  = 7     /* pictuer encode, JPEG, etc */
+};
+
+struct psb_video_ctx {
+       struct list_head head;
+       struct file *filp; /* DRM device file pointer */
+       int ctx_type; /* profile<<8|entrypoint */
+       /* todo: more context specific data for multi-context support */
+};
+
+typedef int (*pfn_vsync_handler)(struct drm_device* dev, int pipe);
+
+
+#define MODE_SETTING_IN_CRTC   0x1
+#define MODE_SETTING_IN_ENCODER 0x2
+#define MODE_SETTING_ON_GOING  0x3
+#define MODE_SETTING_IN_DSR    0x4
+#define MODE_SETTING_ENCODER_DONE 0x8
+#define GCT_R10_HEADER_SIZE    16
+#define GCT_R10_DISPLAY_DESC_SIZE      28
+
+struct drm_psb_private {
+       /*
+        * DSI info. 
+        */
+       void * dbi_dsr_info;    
+#ifdef CONFIG_MDFLD_DSI_DPU
+       void * dbi_dpu_info;
+#endif 
+       void * dsi_configs[2];
+
+       struct work_struct te_work;
+       int te_pipe;
+
+       /*
+        *TTM Glue.
+        */
+
+       struct drm_global_reference mem_global_ref;
+       struct ttm_bo_global_ref bo_global_ref;
+       int has_global;
+
+       struct drm_device *dev;
+       struct ttm_object_device *tdev;
+       struct ttm_fence_device fdev;
+       struct ttm_bo_device bdev;
+       struct ttm_lock ttm_lock;
+       struct vm_operations_struct *ttm_vm_ops;
+       int has_fence_device;
+       int has_bo_device;
+
+       unsigned long chipset;
+
+       struct drm_psb_dev_info_arg dev_info;
+       struct drm_psb_uopt uopt;
+
+       struct psb_gtt *pg;
+
+       /*GTT Memory manager*/
+       struct psb_gtt_mm *gtt_mm;
+
+       struct page *scratch_page;
+       uint32_t sequence[PSB_NUM_ENGINES];
+       uint32_t last_sequence[PSB_NUM_ENGINES];
+       uint32_t last_submitted_seq[PSB_NUM_ENGINES];
+
+       struct psb_mmu_driver *mmu;
+       struct psb_mmu_pd *pf_pd;
+
+       uint8_t *sgx_reg;
+       uint8_t __iomem *vdc_reg;
+#ifdef CONFIG_MDFD_GL3
+       uint8_t *gl3_reg;
+#endif
+       uint32_t gatt_free_offset;
+       
+       /* IMG video context */
+       struct list_head video_ctx;
+       /* Current video context */
+       struct psb_video_ctx *topaz_ctx;
+       struct psb_video_ctx *msvdx_ctx;
+       /* previous vieo context */
+       struct psb_video_ctx *last_topaz_ctx;
+       struct psb_video_ctx *last_msvdx_ctx;
+
+       /*
+        *MSVDX
+        */
+       uint8_t *msvdx_reg;
+       atomic_t msvdx_mmu_invaldc;
+       void *msvdx_private;
+
+       /*
+        *TOPAZ
+        */
+       uint8_t *topaz_reg;
+       void *topaz_private;
+       uint8_t topaz_disabled;
+       uint32_t video_device_fuse;
+       atomic_t topaz_mmu_invaldc;
+
+       /*
+        *Fencing / irq.
+        */
+
+       uint32_t vdc_irq_mask;
+       uint32_t pipestat[PSB_NUM_PIPE];
+       bool vblanksEnabledForFlips;
+
+       spinlock_t irqmask_lock;
+       spinlock_t sequence_lock;
+
+       /*
+        *Modesetting
+        */
+       struct psb_intel_mode_device mode_dev;
+
+       struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE];
+       struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
+       uint32_t num_pipe;
+
+       /*
+        * CI share buffer
+        */
+       unsigned int ci_region_start;
+       unsigned int ci_region_size;
+
+       /*
+        * RAR share buffer;
+        */
+       unsigned int rar_region_start;
+       unsigned int rar_region_size;
+
+       /*
+        *Memory managers
+        */
+
+       int have_camera;
+       int have_rar;
+       int have_tt;
+       int have_mem_mmu;
+       struct mutex temp_mem;
+
+       /*
+        *Relocation buffer mapping.
+        */
+
+       spinlock_t reloc_lock;
+       unsigned int rel_mapped_pages;
+       wait_queue_head_t rel_mapped_queue;
+
+       /*
+        *SAREA
+        */
+       struct drm_psb_sarea *sarea_priv;
+
+       /*
+       *OSPM info
+       */
+       uint32_t ospm_base;
+       spinlock_t ospm_lock;
+
+       /*
+        * Sizes info
+        */
+
+       struct drm_psb_sizes_arg sizes;
+
+       uint32_t fuse_reg_value;
+
+       /* vbt (gct) header information*/
+       struct mrst_vbt vbt_data;
+       /* info that is stored from the gct */
+       struct gct_ioctl_arg gct_data;
+       enum panel_type panel_id;
+
+       /* pci revision id for B0:D2:F0 */
+       uint8_t platform_rev_id;
+
+       /*
+        *LVDS info
+        */
+       int backlight_duty_cycle;       /* restore backlight to this value */
+       bool panel_wants_dither;
+       struct drm_display_mode *panel_fixed_mode;
+       struct drm_display_mode *lfp_lvds_vbt_mode;
+       struct drm_display_mode *sdvo_lvds_vbt_mode;
+
+       struct bdb_lvds_backlight *lvds_bl; /*LVDS backlight info from VBT*/
+       struct psb_intel_i2c_chan *lvds_i2c_bus;
+
+       /* Feature bits from the VBIOS*/
+       unsigned int int_tv_support:1;
+       unsigned int lvds_dither:1;
+       unsigned int lvds_vbt:1;
+       unsigned int int_crt_support:1;
+       unsigned int lvds_use_ssc:1;
+       int lvds_ssc_freq;
+       bool is_lvds_on;
+
+/* MRST private date start */
+/*FIXME JLIU7 need to revisit */
+       unsigned int core_freq;
+       uint32_t iLVDS_enable;
+
+       /* pipe config register value */
+       uint32_t pipeconf;
+       uint32_t pipeconf1;
+       uint32_t pipeconf2;
+
+       /* plane control register value */
+       uint32_t dspcntr;
+       uint32_t dspcntr1;
+       uint32_t dspcntr2;
+
+       /* MRST_DSI private date start */
+       struct work_struct dsi_work;
+
+       /*
+        *MRST DSI info
+        */
+
+       /* The DPI panel power on */
+       bool dpi_panel_on;
+
+       /* The DBI panel power on */
+       bool dbi_panel_on;
+
+       /* The DPI display */
+       bool dpi;
+
+       enum mipi_panel_type panel_make;
+
+       /* Set if MIPI encoder wants to control plane/pipe */
+       bool dsi_plane_pipe_control;
+
+       /* status */
+       uint32_t videoModeFormat:2;
+       uint32_t laneCount:3;
+       uint32_t channelNumber:2;
+       uint32_t status_reserved:25;
+
+       /* dual display - DPI & DBI */
+       bool dual_display;
+
+       /* HS or LP transmission */
+       bool lp_transmission;
+
+       /* configuration phase */
+       bool config_phase;
+
+       /* first boot phase */
+       bool first_boot;
+
+       bool is_mipi_on;
+
+       /* DSI clock */
+       uint32_t RRate;
+       uint32_t DDR_Clock;
+       uint32_t DDR_Clock_Calculated;
+       uint32_t ClockBits;
+
+       /* DBI Buffer pointer */
+       u32 DBI_CB_phys;
+       u8 *p_DBI_commandBuffer;
+       uint32_t DBI_CB_pointer;
+       u8 *p_DBI_dataBuffer_orig;
+       u8 *p_DBI_dataBuffer;
+       uint32_t DBI_DB_pointer;
+
+       /* DSI panel spec */
+       uint32_t pixelClock;
+       uint32_t HsyncWidth;
+       uint32_t HbackPorch;
+       uint32_t HfrontPorch;
+       uint32_t HactiveArea;
+       uint32_t VsyncWidth;
+       uint32_t VbackPorch;
+       uint32_t VfrontPorch;
+       uint32_t VactiveArea;
+       uint32_t bpp:5;
+       uint32_t Reserved:27;
+/* MRST_DSI private date end */
+
+/* MDFLD_DSI private date start */
+       /* dual display - DPI & DBI */
+       bool dual_mipi;
+       uint32_t ksel;
+       uint32_t mipi_lane_config;
+       uint32_t mipi_ctrl_display;
+       /*
+        *MRST DSI info
+        */
+       /* The DPI panel power on */
+       bool dpi_panel_on2;
+
+       /* The DBI panel power on */
+       bool dbi_panel_on2;
+
+       /* The DPI display */
+       bool dpi2;
+
+       /* status */
+       uint32_t videoModeFormat2:2;
+       uint32_t laneCount2:3;
+       uint32_t channelNumber2:2;
+       uint32_t status_reserved2:25;
+
+       /* HS or LP transmission */
+       bool lp_transmission2;
+
+       /* configuration phase */
+       bool config_phase2;
+
+       /* DSI clock */
+       uint32_t RRate2;
+       uint32_t DDR_Clock2;
+       uint32_t DDR_Clock_Calculated2;
+       uint32_t ClockBits2;
+
+       /* DBI Buffer pointer */
+       u32 DBI_CB_phys2;
+       u8 *p_DBI_commandBuffer2;
+       uint32_t DBI_CB_pointer2;
+       u8 *p_DBI_dataBuffer_orig2;
+       u8 *p_DBI_dataBuffer2;
+
+       /* DSI panel spec */
+       uint32_t pixelClock2;
+       uint32_t HsyncWidth2;
+       uint32_t HbackPorch2;
+       uint32_t HfrontPorch2;
+       uint32_t HactiveArea2;
+       uint32_t VsyncWidth2;
+       uint32_t VbackPorch2;
+       uint32_t VfrontPorch2;
+       uint32_t VactiveArea2;
+       uint32_t bpp2:5;
+       uint32_t Reserved2:27;
+       struct mdfld_dsi_dbi_output * dbi_output;
+       struct mdfld_dsi_dbi_output * dbi_output2;
+/* MDFLD_DSI private date end */
+
+#ifdef CONFIG_PM_RUNTIME
+       /*runtime PM state*/
+       int rpm_enabled;
+       struct delayed_work rtpm_work;
+#endif
+
+       /*
+        *Register state
+        */
+       uint32_t saveDSPACNTR;
+       uint32_t saveDSPBCNTR;
+       uint32_t savePIPEACONF;
+       uint32_t savePIPEBCONF;
+       uint32_t savePIPEASRC;
+       uint32_t savePIPEBSRC;
+       uint32_t saveFPA0;
+       uint32_t saveFPA1;
+       uint32_t saveDPLL_A;
+       uint32_t saveDPLL_A_MD;
+       uint32_t saveHTOTAL_A;
+       uint32_t saveHBLANK_A;
+       uint32_t saveHSYNC_A;
+       uint32_t saveVTOTAL_A;
+       uint32_t saveVBLANK_A;
+       uint32_t saveVSYNC_A;
+       uint32_t saveDSPASTRIDE;
+       uint32_t saveDSPASIZE;
+       uint32_t saveDSPAPOS;
+       uint32_t saveDSPABASE;
+       uint32_t saveDSPASURF;
+       uint32_t saveDSPASTATUS;
+       uint32_t saveFPB0;
+       uint32_t saveFPB1;
+       uint32_t saveDPLL_B;
+       uint32_t saveDPLL_B_MD;
+       uint32_t saveHTOTAL_B;
+       uint32_t saveHBLANK_B;
+       uint32_t saveHSYNC_B;
+       uint32_t saveVTOTAL_B;
+       uint32_t saveVBLANK_B;
+       uint32_t saveVSYNC_B;
+       uint32_t saveDSPBSTRIDE;
+       uint32_t saveDSPBSIZE;
+       uint32_t saveDSPBPOS;
+       uint32_t saveDSPBBASE;
+       uint32_t saveDSPBSURF;
+       uint32_t saveDSPBSTATUS;
+       uint32_t saveVCLK_DIVISOR_VGA0;
+       uint32_t saveVCLK_DIVISOR_VGA1;
+       uint32_t saveVCLK_POST_DIV;
+       uint32_t saveVGACNTRL;
+       uint32_t saveADPA;
+       uint32_t saveLVDS;
+       uint32_t saveDVOA;
+       uint32_t saveDVOB;
+       uint32_t saveDVOC;
+       uint32_t savePP_ON;
+       uint32_t savePP_OFF;
+       uint32_t savePP_CONTROL;
+       uint32_t savePP_CYCLE;
+       uint32_t savePFIT_CONTROL;
+       uint32_t savePaletteA[256];
+       uint32_t savePaletteB[256];
+       uint32_t saveBLC_PWM_CTL2;
+       uint32_t saveBLC_PWM_CTL;
+       uint32_t saveCLOCKGATING;
+       uint32_t saveDSPARB;
+       uint32_t saveDSPATILEOFF;
+       uint32_t saveDSPBTILEOFF;
+       uint32_t saveDSPAADDR;
+       uint32_t saveDSPBADDR;
+       uint32_t savePFIT_AUTO_RATIOS;
+       uint32_t savePFIT_PGM_RATIOS;
+       uint32_t savePP_ON_DELAYS;
+       uint32_t savePP_OFF_DELAYS;
+       uint32_t savePP_DIVISOR;
+       uint32_t saveBSM;
+       uint32_t saveVBT;
+       uint32_t saveBCLRPAT_A;
+       uint32_t saveBCLRPAT_B;
+       uint32_t saveDSPALINOFF;
+       uint32_t saveDSPBLINOFF;
+       uint32_t savePERF_MODE;
+       uint32_t saveDSPFW1;
+       uint32_t saveDSPFW2;
+       uint32_t saveDSPFW3;
+       uint32_t saveDSPFW4;
+       uint32_t saveDSPFW5;
+       uint32_t saveDSPFW6;
+       uint32_t saveCHICKENBIT;
+       uint32_t saveDSPACURSOR_CTRL;
+       uint32_t saveDSPBCURSOR_CTRL;
+       uint32_t saveDSPACURSOR_BASE;
+       uint32_t saveDSPBCURSOR_BASE;
+       uint32_t saveDSPACURSOR_POS;
+       uint32_t saveDSPBCURSOR_POS;
+       uint32_t save_palette_a[256];
+       uint32_t save_palette_b[256];
+       uint32_t saveOV_OVADD;
+       uint32_t saveOV_OGAMC0;
+       uint32_t saveOV_OGAMC1;
+       uint32_t saveOV_OGAMC2;
+       uint32_t saveOV_OGAMC3;
+       uint32_t saveOV_OGAMC4;
+       uint32_t saveOV_OGAMC5;
+       uint32_t saveOVC_OVADD;
+       uint32_t saveOVC_OGAMC0;
+       uint32_t saveOVC_OGAMC1;
+       uint32_t saveOVC_OGAMC2;
+       uint32_t saveOVC_OGAMC3;
+       uint32_t saveOVC_OGAMC4;
+       uint32_t saveOVC_OGAMC5;
+
+       /*
+        * extra MDFLD Register state
+        */
+       uint32_t saveHDMIPHYMISCCTL;
+       uint32_t saveHDMIB_CONTROL;
+       uint32_t saveDSPCCNTR;
+       uint32_t savePIPECCONF;
+       uint32_t savePIPECSRC;
+       uint32_t saveHTOTAL_C;
+       uint32_t saveHBLANK_C;
+       uint32_t saveHSYNC_C;
+       uint32_t saveVTOTAL_C;
+       uint32_t saveVBLANK_C;
+       uint32_t saveVSYNC_C;
+       uint32_t saveDSPCSTRIDE;
+       uint32_t saveDSPCSIZE;
+       uint32_t saveDSPCPOS;
+       uint32_t saveDSPCSURF;
+       uint32_t saveDSPCSTATUS;
+       uint32_t saveDSPCLINOFF;
+       uint32_t saveDSPCTILEOFF;
+       uint32_t saveDSPCCURSOR_CTRL;
+       uint32_t saveDSPCCURSOR_BASE;
+       uint32_t saveDSPCCURSOR_POS;
+       uint32_t save_palette_c[256];
+       uint32_t saveOV_OVADD_C;
+       uint32_t saveOV_OGAMC0_C;
+       uint32_t saveOV_OGAMC1_C;
+       uint32_t saveOV_OGAMC2_C;
+       uint32_t saveOV_OGAMC3_C;
+       uint32_t saveOV_OGAMC4_C;
+       uint32_t saveOV_OGAMC5_C;
+
+       /* DSI reg save */
+       uint32_t saveDEVICE_READY_REG;
+       uint32_t saveINTR_EN_REG;
+       uint32_t saveDSI_FUNC_PRG_REG;
+       uint32_t saveHS_TX_TIMEOUT_REG;
+       uint32_t saveLP_RX_TIMEOUT_REG;
+       uint32_t saveTURN_AROUND_TIMEOUT_REG;
+       uint32_t saveDEVICE_RESET_REG;
+       uint32_t saveDPI_RESOLUTION_REG;
+       uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
+       uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
+       uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
+       uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
+       uint32_t saveVERT_SYNC_PAD_COUNT_REG;
+       uint32_t saveVERT_BACK_PORCH_COUNT_REG;
+       uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
+       uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
+       uint32_t saveINIT_COUNT_REG;
+       uint32_t saveMAX_RET_PAK_REG;
+       uint32_t saveVIDEO_FMT_REG;
+       uint32_t saveEOT_DISABLE_REG;
+       uint32_t saveLP_BYTECLK_REG;
+       uint32_t saveHS_LS_DBI_ENABLE_REG;
+       uint32_t saveTXCLKESC_REG;
+       uint32_t saveDPHY_PARAM_REG;
+       uint32_t saveMIPI_CONTROL_REG;
+       uint32_t saveMIPI;
+       uint32_t saveMIPI_C;
+       void (*init_drvIC)(struct drm_device *dev);
+       void (*dsi_prePowerState)(struct drm_device *dev);
+       void (*dsi_postPowerState)(struct drm_device *dev);
+
+       /* DPST Register Save */
+       uint32_t saveHISTOGRAM_INT_CONTROL_REG;
+       uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
+       uint32_t savePWM_CONTROL_LOGIC;
+
+       /* MSI reg save */
+
+       uint32_t msi_addr;
+       uint32_t msi_data;
+
+       /*
+        *Scheduling.
+        */
+
+       struct mutex reset_mutex;
+       struct psb_scheduler scheduler;
+       struct mutex cmdbuf_mutex;
+       /*uint32_t ta_mem_pages;
+       struct psb_ta_mem *ta_mem;
+       int force_ta_mem_load;*/
+
+       /*
+        *TODO: change this to be per drm-context.
+        */
+
+       struct psb_context context;
+
+       /*
+        *Watchdog
+        */
+
+       spinlock_t watchdog_lock;
+       struct timer_list watchdog_timer;
+       struct work_struct watchdog_wq;
+       struct work_struct msvdx_watchdog_wq;
+       struct work_struct topaz_watchdog_wq;
+       int timer_available;
+
+       uint32_t apm_reg;
+       uint16_t apm_base;
+#ifdef OSPM_STAT
+       unsigned char graphics_state;
+       unsigned long gfx_on_time;
+       unsigned long gfx_off_time;
+       unsigned long gfx_last_mode_change;
+       unsigned long gfx_on_cnt;
+       unsigned long gfx_off_cnt;
+#endif
+
+       /*to be removed later*/
+       /*int dri_page_flipping;
+       int current_page;
+#if MDFLD_HDMI_JLIU7
+       int pipe_active[3];
+#else 
+       int pipe_active[2];
+#endif 
+       int saved_start[2];
+       int saved_offset[2];
+       int saved_stride[2];
+
+       int flip_start[2];
+       int flip_offset[2];
+       int flip_stride[2];*/
+
+
+       /*
+        * Used for modifying backlight from
+        * xrandr -- consider removing and using HAL instead
+        */
+       struct drm_property *backlight_property;
+       uint32_t blc_adj1;
+       uint32_t blc_adj2;
+
+       /*
+        * DPST and Hotplug state
+        */
+
+       struct dpst_state *psb_dpst_state;
+       struct hotplug_state *psb_hotplug_state;
+       pfn_vsync_handler psb_vsync_handler;
+
+       struct mutex dsr_mutex;
+       bool b_dsr;
+       bool b_dsr_enable;
+       bool dsr_fb_update_done_0;
+       bool dsr_fb_update_done_2;
+       uint32_t dsr_fb_update;
+       uint32_t dsr_idle_count;
+
+       /*
+        *   Flag letting us know if we have a swapchain or not (DGA)
+        */
+       uint32_t swap_chain_flag;
+
+       bool dsi_device_ready;
+       bool hdmi_done_reading_edid;
+       bool xserver_start;
+
+       uint32_t tmds_clock_khz;
+       had_event_call_back mdfld_had_event_callbacks;
+       struct snd_intel_had_interface *had_interface;
+       void *had_pvt_data;
+
+       uint32_t hdmi_audio_interrupt_mask;
+
+       /*psb fb dev*/
+       void * fbdev;
+       bool b_pmic_backlight;
+
+       /*pmic register for BL*/
+       uint8_t saveBKLTCNT;
+       uint8_t saveBKLTREQ;
+       uint8_t saveBKLTBRTL;
+};
+
+struct psb_fpriv {
+        int bcd_index;
+       struct ttm_object_file *tfile;
+};
+
+struct psb_mmu_driver;
+
+extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
+extern int drm_pick_crtcs(struct drm_device *dev);
+
+
+static inline struct psb_fpriv *psb_fpriv(struct drm_file *file_priv)
+{
+       PVRSRV_FILE_PRIVATE_DATA *pvr_file_priv
+                       = (PVRSRV_FILE_PRIVATE_DATA *)file_priv->driver_priv;
+       return (struct psb_fpriv *) pvr_file_priv->pPriv;
+}
+
+static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
+{
+       return (struct drm_psb_private *) dev->dev_private;
+}
+
+/*
+ *TTM glue. psb_ttm_glue.c
+ */
+
+extern int psb_open(struct inode *inode, struct file *filp);
+extern int psb_release(struct inode *inode, struct file *filp);
+extern int psb_mmap(struct file *filp, struct vm_area_struct *vma);
+
+extern int psb_fence_signaled_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+extern int psb_verify_access(struct ttm_buffer_object *bo,
+                            struct file *filp);
+extern ssize_t psb_ttm_read(struct file *filp, char __user *buf,
+                           size_t count, loff_t *f_pos);
+extern ssize_t psb_ttm_write(struct file *filp, const char __user *buf,
+                           size_t count, loff_t *f_pos);
+extern int psb_fence_finish_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv);
+extern int psb_fence_unref_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+extern int psb_pl_waitidle_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+extern int psb_pl_setstatus_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv);
+extern int psb_pl_synccpu_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int psb_pl_unref_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+extern int psb_pl_reference_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv);
+extern int psb_pl_create_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv);
+extern int psb_pl_ub_create_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv);
+extern int psb_extension_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv);
+extern int psb_ttm_global_init(struct drm_psb_private *dev_priv);
+extern void psb_ttm_global_release(struct drm_psb_private *dev_priv);
+extern int psb_getpageaddrs_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+/*
+ *MMU stuff.
+ */
+
+extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+                                       int trap_pagefaults,
+                                       int invalid_type,
+                                       struct drm_psb_private *dev_priv);
+extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
+extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
+                                                *driver);
+extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
+                              uint32_t gtt_start, uint32_t gtt_pages);
+extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+                                          int trap_pagefaults,
+                                          int invalid_type);
+extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
+extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
+extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+                                       unsigned long address,
+                                       uint32_t num_pages);
+extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
+                                      uint32_t start_pfn,
+                                      unsigned long address,
+                                      uint32_t num_pages, int type);
+extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+                                 unsigned long *pfn);
+
+/*
+ *Enable / disable MMU for different requestors.
+ */
+
+
+extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
+extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+                               unsigned long address, uint32_t num_pages,
+                               uint32_t desired_tile_stride,
+                               uint32_t hw_tile_stride, int type);
+extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
+                                unsigned long address, uint32_t num_pages,
+                                uint32_t desired_tile_stride,
+                                uint32_t hw_tile_stride);
+/*
+ *psb_sgx.c
+ */
+
+
+
+extern int psb_cmdbuf_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int psb_reg_submit(struct drm_psb_private *dev_priv,
+                         uint32_t *regs, unsigned int cmds);
+
+
+extern void psb_fence_or_sync(struct drm_file *file_priv,
+                             uint32_t engine,
+                             uint32_t fence_types,
+                             uint32_t fence_flags,
+                             struct list_head *list,
+                             struct psb_ttm_fence_rep *fence_arg,
+                             struct ttm_fence_object **fence_p);
+
+extern void psb_gl3_global_invalidation(struct drm_device *dev);
+
+/*
+ *psb_fence.c
+ */
+
+extern void psb_fence_handler(struct drm_device *dev, uint32_t class);
+
+extern int psb_fence_emit_sequence(struct ttm_fence_device *fdev,
+                                  uint32_t fence_class,
+                                  uint32_t flags, uint32_t *sequence,
+                                  unsigned long *timeout_jiffies);
+extern void psb_fence_error(struct drm_device *dev,
+                           uint32_t class,
+                           uint32_t sequence, uint32_t type, int error);
+extern int psb_ttm_fence_device_init(struct ttm_fence_device *fdev);
+
+/* MSVDX/Topaz stuff */
+extern int psb_remove_videoctx(struct drm_psb_private *dev_priv, struct file *filp);
+
+extern int lnc_video_frameskip(struct drm_device *dev,
+                              uint64_t user_pointer);
+extern int lnc_video_getparam(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+extern int psb_try_power_down_msvdx(struct drm_device *dev);
+
+/*
+ *psb_fb.c
+ */
+extern int psbfb_probed(struct drm_device *dev);
+extern int psbfb_remove(struct drm_device *dev,
+                       struct drm_framebuffer *fb);
+extern int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv);
+extern int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+extern void *psbfb_vdc_reg(struct drm_device* dev);
+
+/* modesetting */
+extern void psb_modeset_init(struct drm_device *dev);
+extern void psb_modeset_cleanup(struct drm_device *dev);
+
+/*fbdev*/
+extern int psb_fbdev_init(struct drm_device * dev);
+
+/* psb_bl.c */
+int psb_backlight_init(struct drm_device *dev);
+void psb_backlight_exit(void);
+int psb_set_brightness(struct backlight_device *bd);
+int psb_get_brightness(struct backlight_device *bd);
+struct backlight_device * psb_get_backlight_device(void);
+
+/*
+ *Debug print bits setting
+ */
+#define PSB_D_GENERAL (1 << 0)
+#define PSB_D_INIT    (1 << 1)
+#define PSB_D_IRQ     (1 << 2)
+#define PSB_D_ENTRY   (1 << 3)
+/* debug the get H/V BP/FP count */
+#define PSB_D_HV      (1 << 4)
+#define PSB_D_DBI_BF  (1 << 5)
+#define PSB_D_PM      (1 << 6)
+#define PSB_D_RENDER  (1 << 7)
+#define PSB_D_REG     (1 << 8)
+#define PSB_D_MSVDX   (1 << 9)
+#define PSB_D_TOPAZ   (1 << 10)
+
+#ifndef DRM_DEBUG_CODE
+/* To enable debug printout, set drm_psb_debug in psb_drv.c
+ * to any combination of above print flags.
+ */
+/* #define DRM_DEBUG_CODE 2 */
+#endif
+
+extern int drm_psb_debug;
+extern int drm_psb_no_fb;
+extern int drm_psb_disable_vsync;
+extern int drm_topaz_sbuswa;
+
+#define PSB_DEBUG_GENERAL(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_GENERAL, _fmt, ##_arg)
+#define PSB_DEBUG_INIT(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_INIT, _fmt, ##_arg)
+#define PSB_DEBUG_IRQ(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_IRQ, _fmt, ##_arg)
+#define PSB_DEBUG_ENTRY(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_ENTRY, _fmt, ##_arg)
+#define PSB_DEBUG_HV(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_HV, _fmt, ##_arg)
+#define PSB_DEBUG_DBI_BF(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_DBI_BF, _fmt, ##_arg)
+#define PSB_DEBUG_PM(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_PM, _fmt, ##_arg)
+#define PSB_DEBUG_RENDER(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_RENDER, _fmt, ##_arg)
+#define PSB_DEBUG_REG(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_REG, _fmt, ##_arg)
+#define PSB_DEBUG_MSVDX(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_MSVDX, _fmt, ##_arg)
+#define PSB_DEBUG_TOPAZ(_fmt, _arg...) \
+       PSB_DEBUG(PSB_D_TOPAZ, _fmt, ##_arg)
+
+#if DRM_DEBUG_CODE
+#define PSB_DEBUG(_flag, _fmt, _arg...)                                        \
+       do {                                                            \
+               if (unlikely((_flag) & drm_psb_debug))                  \
+                       printk(KERN_DEBUG                               \
+                              "[psb:0x%02x:%s] " _fmt , _flag,         \
+                              __func__ , ##_arg);                      \
+       } while (0)
+#else
+#define PSB_DEBUG(_fmt, _arg...)     do { } while (0)
+#endif
+
+/*
+ *Utilities
+ */
+#define DRM_DRIVER_PRIVATE_T struct drm_psb_private
+
+static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
+{
+       int mcr = (0x10<<24) | (port << 16) | (offset << 8);
+       uint32_t ret_val = 0;
+       struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
+       pci_write_config_dword (pci_root, 0xD0, mcr);
+       pci_read_config_dword (pci_root, 0xD4, &ret_val);
+       pci_dev_put(pci_root);
+       return ret_val;
+}
+static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
+{
+       int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
+       struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
+       pci_write_config_dword (pci_root, 0xD4, value);
+       pci_write_config_dword (pci_root, 0xD0, mcr);
+       pci_dev_put(pci_root);
+}
+
+static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int reg_val = ioread32(dev_priv->vdc_reg + (reg));
+       PSB_DEBUG_REG("reg = 0x%x. reg_val = 0x%x. \n", reg, reg_val);
+       return reg_val;
+}
+
+#define REG_READ(reg)         REGISTER_READ(dev, (reg))
+static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg,
+                                     uint32_t val)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       if ((reg < 0x70084 || reg >0x70088) && (reg < 0xa000 || reg >0xa3ff))
+               PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+       iowrite32((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE(reg, val)    REGISTER_WRITE(dev, (reg), (val))
+
+static inline void REGISTER_WRITE16(struct drm_device *dev,
+                                       uint32_t reg, uint32_t val)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+       iowrite16((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE16(reg, val)    REGISTER_WRITE16(dev, (reg), (val))
+
+static inline void REGISTER_WRITE8(struct drm_device *dev,
+                                      uint32_t reg, uint32_t val)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+       iowrite8((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE8(reg, val)    REGISTER_WRITE8(dev, (reg), (val))
+
+#define PSB_WVDC32(_val, _offs) \
+  iowrite32(_val, dev_priv->vdc_reg + (_offs))
+#define PSB_RVDC32(_offs) \
+  ioread32(dev_priv->vdc_reg + (_offs))
+
+/* #define TRAP_SGX_PM_FAULT 1 */
+#ifdef TRAP_SGX_PM_FAULT
+#define PSB_RSGX32(_offs)                                      \
+({                                                             \
+    if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) {         \
+       printk(KERN_ERR "access sgx when it's off!! (READ) %s, %d\n", \
+              __FILE__, __LINE__);                             \
+       mdelay(1000);                                           \
+    }                                                          \
+    ioread32(dev_priv->sgx_reg + (_offs));                     \
+})
+#else
+#define PSB_RSGX32(_offs)                                      \
+  ioread32(dev_priv->sgx_reg + (_offs))
+#endif
+
+#define MSVDX_REG_DUMP 0
+#if MSVDX_REG_DUMP
+
+#define PSB_WMSVDX32(_val, _offs) \
+  printk("MSVDX: write %08x to reg 0x%08x\n", (unsigned int)(_val), (unsigned int)(_offs));\
+  iowrite32(_val, dev_priv->msvdx_reg + (_offs))
+#define PSB_RMSVDX32(_offs) \
+  ioread32(dev_priv->msvdx_reg + (_offs))
+
+#else
+
+#define PSB_WMSVDX32(_val, _offs) \
+  iowrite32(_val, dev_priv->msvdx_reg + (_offs))
+#define PSB_RMSVDX32(_offs) \
+  ioread32(dev_priv->msvdx_reg + (_offs))
+
+#endif
+
+#define IS_PENWELL(dev) 0 /* FIXME */
+
+extern int drm_psb_ospm;
+extern int drm_psb_cpurelax;
+extern int drm_psb_udelaydivider;
+extern int drm_psb_udelaymultiplier;
+extern int drm_psb_gl3_enable;
+extern int drm_psb_topaz_clockgating;
+
+extern char HDMI_EDID[20];
+
+#ifdef CONFIG_PM_RUNTIME
+extern int gfxrtdelay;
+#endif
+
+#define PSB_UDELAY(usec)                        \
+do {                                            \
+       if (drm_psb_cpurelax == 0)              \
+               DRM_UDELAY(usec * drm_psb_udelaymultiplier\
+                       / drm_psb_udelaydivider);\
+       else                                    \
+               cpu_relax();                    \
+} while (0)
+
+#endif
diff --git a/drivers/staging/mrst/drv/psb_fb.c b/drivers/staging/mrst/drv/psb_fb.c
new file mode 100644 (file)
index 0000000..875c73a
--- /dev/null
@@ -0,0 +1,729 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "psb_ttm_userobj_api.h"
+#include "psb_fb.h"
+#include "psb_pvr_glue.h"
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+extern int MRSTLFBHandleChangeFB(struct drm_device* dev, struct psb_framebuffer *psbfb);
+
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+                                             struct drm_file *file_priv,
+                                             unsigned int *handle);
+
+static const struct drm_framebuffer_funcs psb_fb_funcs = {
+       .destroy = psb_user_framebuffer_destroy,
+       .create_handle = psb_user_framebuffer_create_handle,
+};
+
+#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+
+void *psbfb_vdc_reg(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv;
+       dev_priv = (struct drm_psb_private *) dev->dev_private;
+       return dev_priv->vdc_reg;
+}
+/*EXPORT_SYMBOL(psbfb_vdc_reg); */
+
+static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       struct psb_fbdev * fbdev = info->par;
+       struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+       uint32_t v;
+
+       if (!fb)
+               return -ENOMEM;
+
+       if (regno > 255)
+               return 1;
+
+       red = CMAP_TOHW(red, info->var.red.length);
+       blue = CMAP_TOHW(blue, info->var.blue.length);
+       green = CMAP_TOHW(green, info->var.green.length);
+       transp = CMAP_TOHW(transp, info->var.transp.length);
+
+       v = (red << info->var.red.offset) |
+           (green << info->var.green.offset) |
+           (blue << info->var.blue.offset) |
+           (transp << info->var.transp.offset);
+
+       if (regno < 16) {
+               switch (fb->bits_per_pixel) {
+               case 16:
+                       ((uint32_t *) info->pseudo_palette)[regno] = v;
+                       break;
+               case 24:
+               case 32:
+                       ((uint32_t *) info->pseudo_palette)[regno] = v;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int psbfb_kms_off(struct drm_device *dev, int suspend)
+{
+       struct drm_framebuffer *fb = NULL;
+       struct psb_framebuffer * psbfb = to_psb_fb(fb);
+       DRM_DEBUG("psbfb_kms_off_ioctl\n");
+
+       mutex_lock(&dev->mode_config.mutex);
+       list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+               struct fb_info *info = psbfb->fbdev;
+
+               if (suspend) {
+                       fb_set_suspend(info, 1);
+                       drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
+               }
+       }
+       mutex_unlock(&dev->mode_config.mutex);
+       return 0;
+}
+
+int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       int ret;
+
+       if (drm_psb_no_fb)
+               return 0;
+       console_lock();
+       ret = psbfb_kms_off(dev, 0);
+       console_unlock();
+
+       return ret;
+}
+
+static int psbfb_kms_on(struct drm_device *dev, int resume)
+{
+       struct drm_framebuffer *fb = NULL;
+       struct psb_framebuffer * psbfb = to_psb_fb(fb);
+
+       DRM_DEBUG("psbfb_kms_on_ioctl\n");
+
+       mutex_lock(&dev->mode_config.mutex);
+       list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+               struct fb_info *info = psbfb->fbdev;
+
+               if (resume) {
+                       fb_set_suspend(info, 0);
+                       drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
+               }
+       }
+       mutex_unlock(&dev->mode_config.mutex);
+
+       return 0;
+}
+
+int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       int ret;
+
+       if (drm_psb_no_fb)
+               return 0;
+       console_lock();
+       ret = psbfb_kms_on(dev, 0);
+       console_unlock();
+       drm_helper_disable_unused_functions(dev);
+       return ret;
+}
+
+static void psbfb_suspend(struct drm_device *dev)
+{
+       console_lock();
+       psbfb_kms_off(dev, 1);
+       console_unlock();
+}
+
+static void psbfb_resume(struct drm_device *dev)
+{
+       console_lock();
+       psbfb_kms_on(dev, 1);
+       console_unlock();
+       drm_helper_disable_unused_functions(dev);
+}
+
+static struct fb_ops psbfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var = drm_fb_helper_check_var,
+       .fb_set_par = drm_fb_helper_set_par,
+       .fb_blank = drm_fb_helper_blank,
+       .fb_setcolreg = psbfb_setcolreg,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+};
+
+static struct drm_framebuffer *psb_framebuffer_create
+                       (struct drm_device *dev, struct drm_mode_fb_cmd *r,
+                        void *mm_private)
+{
+       struct psb_framebuffer *fb;
+       int ret;
+
+       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+       if (!fb)
+               return NULL;
+
+       ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
+
+       if (ret)
+               goto err;
+
+       drm_helper_mode_fill_fb_struct(&fb->base, r);
+
+       fb->pvrBO = mm_private;
+
+       return &fb->base;
+
+err:
+       kfree(fb);
+       return NULL;
+}
+
+static struct drm_framebuffer *psb_user_framebuffer_create
+                       (struct drm_device *dev, struct drm_file *filp,
+                        struct drm_mode_fb_cmd *r)
+{
+       struct psb_framebuffer *psbfb;
+       struct drm_framebuffer *fb;
+       struct fb_info *info;
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+       IMG_HANDLE hKernelMemInfo = (IMG_HANDLE)r->handle;
+       struct drm_psb_private *dev_priv
+               = (struct drm_psb_private *) dev->dev_private;
+       struct psb_fbdev * fbdev = dev_priv->fbdev;
+       struct psb_gtt *pg = dev_priv->pg;
+       int ret;
+       uint32_t offset;
+       uint64_t size;
+
+       ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+       if (ret) {
+               DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
+                         (IMG_UINT32)hKernelMemInfo);
+
+               return NULL;
+       }
+
+       DRM_DEBUG("Got Kernel MemInfo for handle %p\n", hKernelMemInfo);
+
+       /* JB: TODO not drop, make smarter */
+       size = psKernelMemInfo->ui32AllocSize;
+       if (size < r->height * r->pitch)
+               return NULL;
+
+       /* JB: TODO not drop, refcount buffer */
+       /* return psb_framebuffer_create(dev, r, bo); */
+
+       fb = psb_framebuffer_create(dev, r, (void *)psKernelMemInfo);
+       if (!fb) {
+               DRM_ERROR("failed to allocate fb.\n");
+               return NULL;
+       }
+
+       psbfb = to_psb_fb(fb);
+       psbfb->size = size;
+       psbfb->hKernelMemInfo = hKernelMemInfo;
+
+       DRM_DEBUG("Mapping to gtt..., KernelMemInfo %p\n", psKernelMemInfo);
+
+       /*if not VRAM, map it into tt aperture*/
+       if (psKernelMemInfo->pvLinAddrKM != pg->vram_addr) {
+               ret = psb_gtt_map_meminfo(dev, hKernelMemInfo, &offset);
+               if (ret) {
+                       DRM_ERROR("map meminfo for 0x%x failed\n",
+                                 (IMG_UINT32)hKernelMemInfo);
+                       return NULL;
+               }
+               psbfb->offset = (offset << PAGE_SHIFT);
+       } else {
+               psbfb->offset = 0;
+       }
+       info = framebuffer_alloc(0, &dev->pdev->dev);
+       if (!info)
+               return NULL;
+
+       strcpy(info->fix.id, "psbfb");
+
+       info->flags = FBINFO_DEFAULT;
+       info->fbops = &psbfb_ops;
+
+       info->fix.smem_start = dev->mode_config.fb_base;
+       info->fix.smem_len = size;
+
+       info->screen_base = psKernelMemInfo->pvLinAddrKM;
+       info->screen_size = size;
+
+       drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+       drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, fb->width, fb->height);
+
+       info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
+       info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
+
+       info->pixmap.size = 64 * 1024;
+       info->pixmap.buf_align = 8;
+       info->pixmap.access_align = 32;
+       info->pixmap.flags = FB_PIXMAP_SYSTEM;
+       info->pixmap.scan_align = 1;
+
+       psbfb->fbdev = info;
+       fbdev->pfb = psbfb;
+
+       fbdev->psb_fb_helper.fb = fb;
+       fbdev->psb_fb_helper.fbdev = info;
+       MRSTLFBHandleChangeFB(dev, psbfb);
+
+       return fb;
+}
+
+static int psbfb_create(struct psb_fbdev * fbdev, struct drm_fb_helper_surface_size * sizes) 
+{
+       struct drm_device * dev = fbdev->psb_fb_helper.dev;
+       struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt *pg = dev_priv->pg;
+       struct fb_info * info;
+       struct drm_framebuffer *fb;
+       struct psb_framebuffer * psbfb;
+       struct drm_mode_fb_cmd mode_cmd;
+       struct device * device = &dev->pdev->dev;
+       int size, aligned_size;
+       int ret;
+
+       mode_cmd.width = sizes->surface_width;
+       mode_cmd.height = sizes->surface_height;
+
+       mode_cmd.bpp = 32;
+        //HW requires pitch to be 64 byte aligned
+        mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
+        mode_cmd.depth = 24;
+
+       size = mode_cmd.pitch * mode_cmd.height;
+       aligned_size = ALIGN(size, PAGE_SIZE);
+
+       mutex_lock(&dev->struct_mutex);
+        fb = psb_framebuffer_create(dev, &mode_cmd, NULL);
+        if (!fb) {
+                DRM_ERROR("failed to allocate fb.\n");
+                ret = -ENOMEM;
+                goto out_err0;
+        }
+        psbfb = to_psb_fb(fb);
+        psbfb->size = size;
+
+       info = framebuffer_alloc(sizeof(struct psb_fbdev), device);
+       if(!info) {
+               ret = -ENOMEM;
+               goto out_err1;
+       }
+
+       info->par = fbdev;
+
+       psbfb->fbdev = info;
+
+       fbdev->psb_fb_helper.fb = fb;
+       fbdev->psb_fb_helper.fbdev = info;
+       fbdev->pfb = psbfb;
+
+       strcpy(info->fix.id, "psbfb");
+
+       info->flags = FBINFO_DEFAULT;
+       info->fbops = &psbfb_ops;
+       info->fix.smem_start = dev->mode_config.fb_base;
+       info->fix.smem_len = size;
+       info->screen_base = (char *)pg->vram_addr;
+       info->screen_size = size;
+       memset(info->screen_base, 0, size);
+
+       drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+       drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, sizes->fb_width, sizes->fb_height);
+
+       info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
+       info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
+
+       info->pixmap.size = 64 * 1024;
+       info->pixmap.buf_align = 8;
+       info->pixmap.access_align = 32;
+       info->pixmap.flags = FB_PIXMAP_SYSTEM;
+       info->pixmap.scan_align = 1;
+
+       DRM_DEBUG("fb depth is %d\n", fb->depth);
+       DRM_DEBUG("   pitch is %d\n", fb->pitch);
+
+       printk(KERN_INFO"allocated %dx%d fb\n", psbfb->base.width, psbfb->base.height); 
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+out_err0:
+       fb->funcs->destroy(fb);
+out_err1:
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno)
+{
+       DRM_DEBUG("%s\n", __FUNCTION__);
+}
+
+static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno)
+{
+       DRM_DEBUG("%s\n", __FUNCTION__);
+}
+
+static int psbfb_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes)
+{
+       struct psb_fbdev * psb_fbdev = (struct psb_fbdev *)helper;
+       int new_fb = 0;
+       int ret;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       if(!helper->fb) {
+               ret = psbfb_create(psb_fbdev, sizes);
+               if(ret) {
+                       return ret;
+               }
+
+               new_fb = 1;
+       }
+
+       return new_fb;
+}
+
+static struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+       .gamma_set = psbfb_gamma_set,
+       .gamma_get = psbfb_gamma_get,
+       .fb_probe = psbfb_probe,
+};
+
+static int psb_fbdev_destroy(struct drm_device * dev, struct psb_fbdev * fbdev)
+{
+       struct fb_info * info;
+       struct psb_framebuffer * psbfb = fbdev->pfb;
+
+       if(fbdev->psb_fb_helper.fbdev) {
+               info = fbdev->psb_fb_helper.fbdev;
+               unregister_framebuffer(info);
+               iounmap(info->screen_base);
+               framebuffer_release(info);
+       }
+
+       drm_fb_helper_fini(&fbdev->psb_fb_helper);
+
+       drm_framebuffer_cleanup(&psbfb->base);
+       
+       return 0;
+}
+
+int psb_fbdev_init(struct drm_device * dev) 
+{
+       struct psb_fbdev * fbdev;
+       struct drm_psb_private * dev_priv = 
+               (struct drm_psb_private *)dev->dev_private;
+       int num_crtc;
+       
+       fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
+       if(!fbdev) {
+               DRM_ERROR("no memory\n");
+               return -ENOMEM;
+       }
+
+       dev_priv->fbdev = fbdev;
+       fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
+
+       /*FIXME: how many crtc will MDFL support?*/
+       num_crtc = 3;
+
+       drm_fb_helper_init(dev, &fbdev->psb_fb_helper, num_crtc, INTELFB_CONN_LIMIT);
+
+       drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
+       drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
+       return 0;
+}
+
+static void psb_fbdev_fini(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = 
+               (struct drm_psb_private *)dev->dev_private;
+
+       if(!dev_priv->fbdev) {
+               return;
+       }
+
+       psb_fbdev_destroy(dev, dev_priv->fbdev);
+       kfree(dev_priv->fbdev);
+       dev_priv->fbdev = NULL;
+}
+
+static void psbfb_output_poll_changed(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+       struct psb_fbdev * fbdev = (struct psb_fbdev *)dev_priv->fbdev;
+       drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
+}
+
+int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
+{
+       struct fb_info *info;
+       struct psb_framebuffer * psbfb = to_psb_fb(fb);
+
+       if (drm_psb_no_fb)
+               return 0;
+
+       info = psbfb->fbdev;
+       psbfb->pvrBO = NULL;
+       MRSTLFBHandleChangeFB(dev, psbfb);
+
+       if (info) {
+               framebuffer_release(info);
+       }
+
+       return 0;
+}
+/*EXPORT_SYMBOL(psbfb_remove); */
+
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+                                             struct drm_file *file_priv,
+                                             unsigned int *handle)
+{
+       /* JB: TODO currently we can't go from a bo to a handle with ttm */
+       (void) file_priv;
+       *handle = 0;
+       return 0;
+}
+
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+       struct drm_device *dev = fb->dev;
+       struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+       /*ummap gtt pages*/
+       psb_gtt_unmap_meminfo(dev, psbfb->hKernelMemInfo);
+       if (psbfb->fbdev)
+               psbfb_remove(dev, fb);
+
+       /* JB: TODO not drop, refcount buffer */
+       drm_framebuffer_cleanup(fb);
+
+       kfree(fb);
+}
+
+static const struct drm_mode_config_funcs psb_mode_funcs = {
+       .fb_create = psb_user_framebuffer_create,
+       .output_poll_changed = psbfb_output_poll_changed,
+};
+
+static int psb_create_backlight_property(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv
+                               = (struct drm_psb_private *) dev->dev_private;
+       struct drm_property *backlight;
+
+       if (dev_priv->backlight_property)
+               return 0;
+
+       backlight = drm_property_create(dev,
+                                       DRM_MODE_PROP_RANGE,
+                                       "backlight",
+                                       2);
+       backlight->values[0] = 0;
+       backlight->values[1] = 100;
+
+       dev_priv->backlight_property = backlight;
+
+       return 0;
+}
+
+static void psb_setup_outputs(struct drm_device *dev)
+{
+       struct drm_connector *connector;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       drm_mode_create_scaling_mode_property(dev);
+
+       psb_create_backlight_property(dev);
+
+       mdfld_output_init(dev);
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list,
+                           head) {
+               struct psb_intel_output *psb_intel_output =
+                   to_psb_intel_output(connector);
+               struct drm_encoder *encoder = &psb_intel_output->enc;
+               int crtc_mask = 0, clone_mask = 0;
+
+               /* valid crtcs */
+               switch (psb_intel_output->type) {
+               case INTEL_OUTPUT_SDVO:
+                       crtc_mask = ((1 << 0) | (1 << 1));
+                       clone_mask = (1 << INTEL_OUTPUT_SDVO);
+                       break;
+               case INTEL_OUTPUT_LVDS:
+                       PSB_DEBUG_ENTRY("LVDS. \n");
+                       crtc_mask = (1 << 1);
+
+                       clone_mask = (1 << INTEL_OUTPUT_LVDS);
+                       break;
+               case INTEL_OUTPUT_MIPI:
+                       PSB_DEBUG_ENTRY("MIPI. \n");
+                       crtc_mask = (1 << 0);
+                       clone_mask = (1 << INTEL_OUTPUT_MIPI);
+                       break;
+               case INTEL_OUTPUT_MIPI2:
+                       PSB_DEBUG_ENTRY("MIPI2. \n");
+                       crtc_mask = (1 << 2);
+                       clone_mask = (1 << INTEL_OUTPUT_MIPI2);
+                       break;
+               case INTEL_OUTPUT_HDMI:
+                       PSB_DEBUG_ENTRY("HDMI. \n");
+                       crtc_mask = (1 << 1);
+                       clone_mask = (1 << INTEL_OUTPUT_HDMI);
+                       break;
+               }
+
+               encoder->possible_crtcs = crtc_mask;
+               encoder->possible_clones =
+                   psb_intel_connector_clones(dev, clone_mask);
+
+       }
+}
+
+static void *psb_bo_from_handle(struct drm_device *dev,
+                               struct drm_file *file_priv,
+                               unsigned int handle)
+{
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+       IMG_HANDLE hKernelMemInfo = (IMG_HANDLE)handle;
+       int ret;
+
+       ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+       if (ret) {
+               DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
+                         (IMG_UINT32)hKernelMemInfo);
+               return NULL;
+       }
+
+       return (void *)psKernelMemInfo;
+}
+
+static size_t psb_bo_size(struct drm_device *dev, void *bof)
+{
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO *)bof;
+       return (size_t)psKernelMemInfo->ui32AllocSize;
+}
+
+static size_t psb_bo_offset(struct drm_device *dev, void *bof)
+{
+       struct psb_framebuffer *psbfb
+               = (struct psb_framebuffer *)bof;
+
+       return (size_t)psbfb->offset;
+}
+
+static int psb_bo_pin_for_scanout(struct drm_device *dev, void *bo)
+{
+        return 0;
+}
+
+static int psb_bo_unpin_for_scanout(struct drm_device *dev, void *bo) 
+{
+       return 0;
+}
+
+void psb_modeset_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) dev->dev_private;
+       struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
+       int i;
+
+       PSB_DEBUG_ENTRY("\n");
+       /* Init mm functions */
+       mode_dev->bo_from_handle = psb_bo_from_handle;
+       mode_dev->bo_size = psb_bo_size;
+       mode_dev->bo_offset = psb_bo_offset;
+       mode_dev->bo_pin_for_scanout = psb_bo_pin_for_scanout;
+       mode_dev->bo_unpin_for_scanout = psb_bo_unpin_for_scanout;
+
+       drm_mode_config_init(dev);
+
+       dev->mode_config.min_width = 0;
+       dev->mode_config.min_height = 0;
+
+       dev->mode_config.funcs = (void *) &psb_mode_funcs;
+
+       /* set memory base */
+       /* MRST and PSB should use BAR 2*/
+       pci_read_config_dword(dev->pdev, PSB_BSM, (uint32_t *) &(dev->mode_config.fb_base));
+
+       for (i = 0; i < dev_priv->num_pipe; i++)
+               psb_intel_crtc_init(dev, i, mode_dev);
+
+       dev->mode_config.max_width = dev->mode_config.num_crtc * MDFLD_PLANE_MAX_WIDTH;
+       dev->mode_config.max_height = dev->mode_config.num_crtc * MDFLD_PLANE_MAX_HEIGHT;
+
+       psb_setup_outputs(dev);
+
+       /* setup fbs */
+       /* drm_initial_config(dev); */
+}
+
+void psb_modeset_cleanup(struct drm_device *dev)
+{
+       mutex_lock(&dev->struct_mutex);
+
+       drm_kms_helper_poll_fini(dev);
+       psb_fbdev_fini(dev);
+       
+       drm_mode_config_cleanup(dev);
+
+       mutex_unlock(&dev->struct_mutex);
+}
diff --git a/drivers/staging/mrst/drv/psb_fb.h b/drivers/staging/mrst/drv/psb_fb.h
new file mode 100644 (file)
index 0000000..5085f8b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2008, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *      Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _PSB_FB_H_
+#define _PSB_FB_H_
+
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+
+#include "psb_drv.h"
+
+/*IMG Headers*/
+#include "servicesint.h"
+
+struct psb_framebuffer {
+       struct drm_framebuffer base;
+       struct address_space *addr_space;
+       struct ttm_buffer_object *bo;
+       struct fb_info * fbdev;
+       /* struct ttm_bo_kmap_obj kmap; */
+       PVRSRV_KERNEL_MEM_INFO *pvrBO;
+       IMG_HANDLE hKernelMemInfo;
+       uint32_t size;
+       uint32_t offset;
+};
+
+struct psb_fbdev {
+       struct drm_fb_helper psb_fb_helper;
+       struct psb_framebuffer * pfb;
+};
+
+#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
+
+
+extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
+
+
+#endif
+
diff --git a/drivers/staging/mrst/drv/psb_gtt.c b/drivers/staging/mrst/drv/psb_gtt.c
new file mode 100644 (file)
index 0000000..e3faa4a
--- /dev/null
@@ -0,0 +1,1035 @@
+/*
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_pvr_glue.h"
+
+static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
+{
+       uint32_t mask = PSB_PTE_VALID;
+
+       if (type & PSB_MMU_CACHED_MEMORY)
+               mask |= PSB_PTE_CACHED;
+       if (type & PSB_MMU_RO_MEMORY)
+               mask |= PSB_PTE_RO;
+       if (type & PSB_MMU_WO_MEMORY)
+               mask |= PSB_PTE_WO;
+
+       return (pfn << PAGE_SHIFT) | mask;
+}
+
+struct psb_gtt *psb_gtt_alloc(struct drm_device *dev) {
+       struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+
+       if (!tmp)
+               return NULL;
+
+       init_rwsem(&tmp->sem);
+       tmp->dev = dev;
+
+       return tmp;
+}
+
+void psb_gtt_takedown(struct psb_gtt *pg, int free)
+{
+       struct drm_psb_private *dev_priv = pg->dev->dev_private;
+
+       if (!pg)
+               return;
+
+       if (pg->gtt_map) {
+               iounmap(pg->gtt_map);
+               pg->gtt_map = NULL;
+       }
+       if (pg->initialized) {
+               pci_write_config_word(pg->dev->pdev, PSB_GMCH_CTRL,
+                                     pg->gmch_ctrl);
+               PSB_WVDC32(pg->pge_ctl, PSB_PGETBL_CTL);
+               (void) PSB_RVDC32(PSB_PGETBL_CTL);
+       }
+       if (free)
+               kfree(pg);
+}
+
+int psb_gtt_init(struct psb_gtt *pg, int resume)
+{
+       struct drm_device *dev = pg->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       unsigned gtt_pages;
+       unsigned long stolen_size, vram_stolen_size, ci_stolen_size;
+       unsigned long rar_stolen_size;
+       unsigned i, num_pages;
+       unsigned pfn_base;
+       uint32_t ci_pages, vram_pages;
+       uint32_t tt_pages;
+       uint32_t __iomem *ttm_gtt_map;
+       uint32_t dvmt_mode = 0;
+
+       int ret = 0;
+       uint32_t pte;
+
+       pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &pg->gmch_ctrl);
+       pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+                             pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+       pg->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
+       PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+       (void) PSB_RVDC32(PSB_PGETBL_CTL);
+
+       pg->initialized = 1;
+
+       pg->gtt_phys_start = pg->pge_ctl & PAGE_MASK;
+
+       pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+       /* fix me: video mmu has hw bug to access 0x0D0000000,
+        * then make gatt start at 0x0e000,0000 */
+       pg->mmu_gatt_start = PSB_MEM_TT_START;
+       pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
+       gtt_pages =
+               pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
+       pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
+                        >> PAGE_SHIFT;
+
+       pci_read_config_dword(dev->pdev, PSB_BSM, &pg->stolen_base);
+       vram_stolen_size = pg->gtt_phys_start - pg->stolen_base - PAGE_SIZE;
+
+       /* CI is not included in the stolen size since the TOPAZ MMU bug */
+       ci_stolen_size = dev_priv->ci_region_size;
+       /* Don't add CI & RAR share buffer space
+        * managed by TTM to stolen_size */
+       stolen_size = vram_stolen_size;
+
+       rar_stolen_size = dev_priv->rar_region_size;
+
+       printk(KERN_INFO"GMMADR(region 0) start: 0x%08x (%dM).\n",
+              pg->gatt_start, pg->gatt_pages / 256);
+       printk(KERN_INFO"GTTADR(region 3) start: 0x%08x (can map %dM RAM), and actual RAM base 0x%08x.\n",
+              pg->gtt_start, gtt_pages * 4, pg->gtt_phys_start);
+       printk(KERN_INFO"Stole memory information \n");
+       printk(KERN_INFO"      base in RAM: 0x%x \n", pg->stolen_base);
+       printk(KERN_INFO"      size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
+              vram_stolen_size / 1024);
+       dvmt_mode = (pg->gmch_ctrl >> 4) & 0x7;
+       printk(KERN_INFO"      the correct size should be: %dM(dvmt mode=%d) \n",
+              (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+
+       if (ci_stolen_size > 0)
+               printk(KERN_INFO"CI Stole memory: RAM base = 0x%08x, size = %lu M \n",
+                      dev_priv->ci_region_start,
+                      ci_stolen_size / 1024 / 1024);
+       if (rar_stolen_size > 0)
+               printk(KERN_INFO"RAR Stole memory: RAM base = 0x%08x, size = %lu M \n",
+                      dev_priv->rar_region_start,
+                      rar_stolen_size / 1024 / 1024);
+
+       if (resume && (gtt_pages != pg->gtt_pages) &&
+           (stolen_size != pg->stolen_size)) {
+               DRM_ERROR("GTT resume error.\n");
+               ret = -EINVAL;
+               goto out_err;
+       }
+
+       pg->gtt_pages = gtt_pages;
+       pg->stolen_size = stolen_size;
+       pg->vram_stolen_size = vram_stolen_size;
+       pg->ci_stolen_size = ci_stolen_size;
+       pg->rar_stolen_size = rar_stolen_size;
+       pg->gtt_map =
+               ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
+       if (!pg->gtt_map) {
+               DRM_ERROR("Failure to map gtt.\n");
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       pg->vram_addr = ioremap_wc(pg->stolen_base, stolen_size);
+       if (!pg->vram_addr) {
+               DRM_ERROR("Failure to map stolen base.\n");
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       DRM_DEBUG("vram kernel virtual address %p\n", pg->vram_addr);
+
+       tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+                  (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+       ttm_gtt_map = pg->gtt_map + tt_pages / 2;
+
+       /*
+        * insert vram stolen pages.
+        */
+
+       pfn_base = pg->stolen_base >> PAGE_SHIFT;
+       vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
+       printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
+              num_pages, pfn_base, 0);
+       for (i = 0; i < num_pages; ++i) {
+               pte = psb_gtt_mask_pte(pfn_base + i, 0);
+               iowrite32(pte, pg->gtt_map + i);
+       }
+
+       /*
+        * Init rest of gtt managed by IMG.
+        */
+       pfn_base = page_to_pfn(dev_priv->scratch_page);
+       pte = psb_gtt_mask_pte(pfn_base, 0);
+       for (; i < tt_pages / 2 - 1; ++i)
+               iowrite32(pte, pg->gtt_map + i);
+
+       /*
+        * insert CI stolen pages
+        */
+
+       pfn_base = dev_priv->ci_region_start >> PAGE_SHIFT;
+       ci_pages = num_pages = ci_stolen_size >> PAGE_SHIFT;
+       printk(KERN_INFO"Set up %d CI stolen pages starting at 0x%08x, GTT offset %dK\n",
+              num_pages, pfn_base, (ttm_gtt_map - pg->gtt_map) * 4);
+       for (i = 0; i < num_pages; ++i) {
+               pte = psb_gtt_mask_pte(pfn_base + i, 0);
+               iowrite32(pte, ttm_gtt_map + i);
+       }
+
+       /*
+        * insert RAR stolen pages
+        */
+       if (rar_stolen_size != 0) {
+               pfn_base = dev_priv->rar_region_start >> PAGE_SHIFT;
+               num_pages = rar_stolen_size >> PAGE_SHIFT;
+               printk(KERN_INFO"Set up %d RAR stolen pages starting at 0x%08x, GTT offset %dK\n",
+                      num_pages, pfn_base,
+                      (ttm_gtt_map - pg->gtt_map + i) * 4);
+               for (; i < num_pages + ci_pages; ++i) {
+                       pte = psb_gtt_mask_pte(pfn_base + i - ci_pages, 0);
+                       iowrite32(pte, ttm_gtt_map + i);
+               }
+       }
+       /*
+        * Init rest of gtt managed by TTM.
+        */
+
+       pfn_base = page_to_pfn(dev_priv->scratch_page);
+       pte = psb_gtt_mask_pte(pfn_base, 0);
+       PSB_DEBUG_INIT("Initializing the rest of a total "
+                      "of %d gtt pages.\n", pg->gatt_pages);
+
+       for (; i < pg->gatt_pages - tt_pages / 2; ++i)
+               iowrite32(pte, ttm_gtt_map + i);
+       (void) ioread32(pg->gtt_map + i - 1);
+
+       return 0;
+
+out_err:
+       psb_gtt_takedown(pg, 0);
+       return ret;
+}
+
+int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
+                        unsigned offset_pages, unsigned num_pages,
+                        unsigned desired_tile_stride,
+                        unsigned hw_tile_stride, int type)
+{
+       unsigned rows = 1;
+       unsigned add;
+       unsigned row_add;
+       unsigned i;
+       unsigned j;
+       uint32_t __iomem *cur_page = NULL;
+       uint32_t pte;
+
+       if (hw_tile_stride)
+               rows = num_pages / desired_tile_stride;
+       else
+               desired_tile_stride = num_pages;
+
+       add = desired_tile_stride;
+       row_add = hw_tile_stride;
+
+       down_read(&pg->sem);
+       for (i = 0; i < rows; ++i) {
+               cur_page = pg->gtt_map + offset_pages;
+               for (j = 0; j < desired_tile_stride; ++j) {
+                       pte =
+                               psb_gtt_mask_pte(page_to_pfn(*pages++), type);
+                       iowrite32(pte, cur_page++);
+               }
+               offset_pages += add;
+       }
+       (void) ioread32(cur_page - 1);
+       up_read(&pg->sem);
+
+       return 0;
+}
+
+static int psb_gtt_insert_phys_addresses(struct psb_gtt *pg, IMG_CPU_PHYADDR *pPhysFrames,
+                                 unsigned offset_pages, unsigned num_pages, int type)
+{
+       unsigned j;
+       uint32_t __iomem *cur_page = NULL;
+       uint32_t pte;
+
+       //printk("Allocatng IMG GTT mem at %x (pages %d)\n",offset_pages,num_pages);
+       down_read(&pg->sem);
+
+       cur_page = pg->gtt_map + offset_pages;
+       for (j = 0; j < num_pages; ++j) {
+               pte =  psb_gtt_mask_pte((pPhysFrames++)->uiAddr >> PAGE_SHIFT, type);
+               iowrite32(pte, cur_page++);
+               //printk("PTE %d: %x/%x\n",j,(pPhysFrames-1)->uiAddr,pte);
+       }
+       (void) ioread32(cur_page - 1);
+
+       up_read(&pg->sem);
+
+       return 0;
+}
+
+int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages,
+                        unsigned num_pages, unsigned desired_tile_stride,
+                        unsigned hw_tile_stride, int rc_prot)
+{
+       struct drm_psb_private *dev_priv = pg->dev->dev_private;
+       unsigned rows = 1;
+       unsigned add;
+       unsigned row_add;
+       unsigned i;
+       unsigned j;
+       uint32_t __iomem *cur_page = NULL;
+       unsigned pfn_base = page_to_pfn(dev_priv->scratch_page);
+       uint32_t pte = psb_gtt_mask_pte(pfn_base, 0);
+
+       if (hw_tile_stride)
+               rows = num_pages / desired_tile_stride;
+       else
+               desired_tile_stride = num_pages;
+
+       add = desired_tile_stride;
+       row_add = hw_tile_stride;
+
+       if (rc_prot)
+               down_read(&pg->sem);
+       for (i = 0; i < rows; ++i) {
+               cur_page = pg->gtt_map + offset_pages;
+               for (j = 0; j < desired_tile_stride; ++j)
+                       iowrite32(pte, cur_page++);
+
+               offset_pages += add;
+       }
+       (void) ioread32(cur_page - 1);
+       if (rc_prot)
+               up_read(&pg->sem);
+
+       return 0;
+}
+
+int psb_gtt_mm_init(struct psb_gtt *pg)
+{
+       struct psb_gtt_mm *gtt_mm;
+       struct drm_psb_private *dev_priv = pg->dev->dev_private;
+       struct drm_open_hash *ht;
+       struct drm_mm *mm;
+       int ret;
+       uint32_t tt_start;
+       uint32_t tt_size;
+
+       if (!pg || !pg->initialized) {
+               DRM_DEBUG("Invalid gtt struct\n");
+               return -EINVAL;
+       }
+
+       gtt_mm =  kzalloc(sizeof(struct psb_gtt_mm), GFP_KERNEL);
+       if (!gtt_mm)
+               return -ENOMEM;
+
+       spin_lock_init(&gtt_mm->lock);
+
+       ht = &gtt_mm->hash;
+       ret = drm_ht_create(ht, 20);
+       if (ret) {
+               DRM_DEBUG("Create hash table failed(%d)\n", ret);
+               goto err_free;
+       }
+
+       tt_start = (pg->stolen_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       tt_start = (tt_start < pg->gatt_pages) ? tt_start : pg->gatt_pages;
+       tt_size = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+                 (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+       mm = &gtt_mm->base;
+
+       /*will use tt_start ~ 128M for IMG TT buffers*/
+       ret = drm_mm_init(mm, tt_start, ((tt_size / 2) - tt_start));
+       if (ret) {
+               DRM_DEBUG("drm_mm_int error(%d)\n", ret);
+               goto err_mm_init;
+       }
+
+       gtt_mm->count = 0;
+
+       dev_priv->gtt_mm = gtt_mm;
+
+       DRM_INFO("PSB GTT mem manager ready, tt_start %ld, tt_size %ld pages\n",
+                (unsigned long)tt_start,
+                (unsigned long)((tt_size / 2) - tt_start));
+       return 0;
+err_mm_init:
+       drm_ht_remove(ht);
+
+err_free:
+       kfree(gtt_mm);
+       return ret;
+}
+
+/**
+ * Delete all hash entries;
+ */
+void psb_gtt_mm_takedown(void)
+{
+       return;
+}
+
+static int psb_gtt_mm_get_ht_by_pid_locked(struct psb_gtt_mm *mm,
+               u32 tgid,
+               struct psb_gtt_hash_entry **hentry)
+{
+       struct drm_hash_item *entry;
+       struct psb_gtt_hash_entry *psb_entry;
+       int ret;
+
+       ret = drm_ht_find_item(&mm->hash, tgid, &entry);
+       if (ret) {
+               DRM_DEBUG("Cannot find entry pid=%u\n", tgid);
+               return ret;
+       }
+
+       psb_entry = container_of(entry, struct psb_gtt_hash_entry, item);
+       if (!psb_entry) {
+               DRM_DEBUG("Invalid entry");
+               return -EINVAL;
+       }
+
+       *hentry = psb_entry;
+       return 0;
+}
+
+
+static int psb_gtt_mm_insert_ht_locked(struct psb_gtt_mm *mm,
+                                      u32 tgid,
+                                      struct psb_gtt_hash_entry *hentry)
+{
+       struct drm_hash_item *item;
+       int ret;
+
+       if (!hentry) {
+               DRM_DEBUG("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       item = &hentry->item;
+       item->key = tgid;
+
+       /**
+        * NOTE: drm_ht_insert_item will perform such a check
+       ret = psb_gtt_mm_get_ht_by_pid(mm, tgid, &tmp);
+       if (!ret) {
+               DRM_DEBUG("Entry already exists for pid %ld\n", tgid);
+               return -EAGAIN;
+       }
+       */
+
+       /*Insert the given entry*/
+       ret = drm_ht_insert_item(&mm->hash, item);
+       if (ret) {
+               DRM_DEBUG("Insert failure\n");
+               return ret;
+       }
+
+       mm->count++;
+
+       return 0;
+}
+
+static int psb_gtt_mm_alloc_insert_ht(struct psb_gtt_mm *mm,
+                                     u32 tgid,
+                                     struct psb_gtt_hash_entry **entry)
+{
+       struct psb_gtt_hash_entry *hentry;
+       int ret;
+
+       /*if the hentry for this tgid exists, just get it and return*/
+       spin_lock(&mm->lock);
+       ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
+       if (!ret) {
+               DRM_DEBUG("Entry for tgid %u exist, hentry %p\n",
+                         tgid, hentry);
+               *entry = hentry;
+               spin_unlock(&mm->lock);
+               return 0;
+       }
+       spin_unlock(&mm->lock);
+
+       DRM_DEBUG("Entry for tgid %u doesn't exist, will create it\n", tgid);
+
+       hentry = kzalloc(sizeof(struct psb_gtt_hash_entry), GFP_KERNEL);
+       if (!hentry) {
+               DRM_DEBUG("Kmalloc failled\n");
+               return -ENOMEM;
+       }
+
+       ret = drm_ht_create(&hentry->ht, 20);
+       if (ret) {
+               DRM_DEBUG("Create hash table failed\n");
+               return ret;
+       }
+
+       spin_lock(&mm->lock);
+       ret = psb_gtt_mm_insert_ht_locked(mm, tgid, hentry);
+       spin_unlock(&mm->lock);
+
+       if (!ret)
+               *entry = hentry;
+
+       return ret;
+}
+
+static struct psb_gtt_hash_entry *
+psb_gtt_mm_remove_ht_locked(struct psb_gtt_mm *mm, u32 tgid) {
+       struct psb_gtt_hash_entry *tmp;
+       int ret;
+
+       ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &tmp);
+       if (ret) {
+               DRM_DEBUG("Cannot find entry pid %u\n", tgid);
+               return NULL;
+       }
+
+       /*remove it from ht*/
+       drm_ht_remove_item(&mm->hash, &tmp->item);
+
+       mm->count--;
+
+       return tmp;
+}
+
+static int psb_gtt_mm_remove_free_ht_locked(struct psb_gtt_mm *mm, u32 tgid)
+{
+       struct psb_gtt_hash_entry *entry;
+
+       entry = psb_gtt_mm_remove_ht_locked(mm, tgid);
+
+       if (!entry) {
+               DRM_DEBUG("Invalid entry");
+               return -EINVAL;
+       }
+
+       /*delete ht*/
+       drm_ht_remove(&entry->ht);
+
+       /*free this entry*/
+       kfree(entry);
+       return 0;
+}
+
+static int
+psb_gtt_mm_get_mem_mapping_locked(struct drm_open_hash *ht,
+                                 u32 key,
+                                 struct psb_gtt_mem_mapping **hentry)
+{
+       struct drm_hash_item *entry;
+       struct psb_gtt_mem_mapping *mapping;
+       int ret;
+
+       ret = drm_ht_find_item(ht, key, &entry);
+       if (ret) {
+               DRM_DEBUG("Cannot find key %u\n", key);
+               return ret;
+       }
+
+       mapping =  container_of(entry, struct psb_gtt_mem_mapping, item);
+       if (!mapping) {
+               DRM_DEBUG("Invalid entry\n");
+               return -EINVAL;
+       }
+
+       *hentry = mapping;
+       return 0;
+}
+
+static int
+psb_gtt_mm_insert_mem_mapping_locked(struct drm_open_hash *ht,
+                                    u32 key,
+                                    struct psb_gtt_mem_mapping *hentry)
+{
+       struct drm_hash_item *item;
+       struct psb_gtt_hash_entry *entry;
+       int ret;
+
+       if (!hentry) {
+               DRM_DEBUG("hentry is NULL\n");
+               return -EINVAL;
+       }
+
+       item = &hentry->item;
+       item->key = key;
+
+       ret = drm_ht_insert_item(ht, item);
+       if (ret) {
+               DRM_DEBUG("insert_item failed\n");
+               return ret;
+       }
+
+       entry = container_of(ht, struct psb_gtt_hash_entry, ht);
+       if (entry)
+               entry->count++;
+
+       return 0;
+}
+
+static int
+psb_gtt_mm_alloc_insert_mem_mapping(struct psb_gtt_mm *mm,
+                                   struct drm_open_hash *ht,
+                                   u32 key,
+                                   struct drm_mm_node *node,
+                                   struct psb_gtt_mem_mapping **entry)
+{
+       struct psb_gtt_mem_mapping *mapping;
+       int ret;
+
+       if (!node || !ht) {
+               DRM_DEBUG("parameter error\n");
+               return -EINVAL;
+       }
+
+       /*try to get this mem_map */
+       spin_lock(&mm->lock);
+       ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &mapping);
+       if (!ret) {
+               DRM_DEBUG("mapping entry for key %u exists, entry %p\n",
+                         key, mapping);
+               *entry = mapping;
+               spin_unlock(&mm->lock);
+               return 0;
+       }
+       spin_unlock(&mm->lock);
+
+       DRM_DEBUG("Mapping entry for key %u doesn't exist, will create it\n",
+                 key);
+
+       mapping = kzalloc(sizeof(struct psb_gtt_mem_mapping), GFP_KERNEL);
+       if (!mapping) {
+               DRM_DEBUG("kmalloc failed\n");
+               return -ENOMEM;
+       }
+
+       mapping->node = node;
+
+       spin_lock(&mm->lock);
+       ret = psb_gtt_mm_insert_mem_mapping_locked(ht, key, mapping);
+       spin_unlock(&mm->lock);
+
+       if (!ret)
+               *entry = mapping;
+
+       return ret;
+}
+
+static struct psb_gtt_mem_mapping *
+psb_gtt_mm_remove_mem_mapping_locked(struct drm_open_hash *ht, u32 key) {
+       struct psb_gtt_mem_mapping *tmp;
+       struct psb_gtt_hash_entry *entry;
+       int ret;
+
+       ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &tmp);
+       if (ret) {
+               DRM_DEBUG("Cannot find key %u\n", key);
+               return NULL;
+       }
+
+       drm_ht_remove_item(ht, &tmp->item);
+
+       entry = container_of(ht, struct psb_gtt_hash_entry, ht);
+       if (entry)
+               entry->count--;
+
+       return tmp;
+}
+
+static int psb_gtt_mm_remove_free_mem_mapping_locked(struct drm_open_hash *ht,
+               u32 key,
+               struct drm_mm_node **node)
+{
+       struct psb_gtt_mem_mapping *entry;
+
+       entry = psb_gtt_mm_remove_mem_mapping_locked(ht, key);
+       if (!entry) {
+               DRM_DEBUG("entry is NULL\n");
+               return -EINVAL;
+       }
+
+       *node = entry->node;
+
+       kfree(entry);
+       return 0;
+}
+
+static int psb_gtt_add_node(struct psb_gtt_mm *mm,
+                           u32 tgid,
+                           u32 key,
+                           struct drm_mm_node *node,
+                           struct psb_gtt_mem_mapping **entry)
+{
+       struct psb_gtt_hash_entry *hentry;
+       struct psb_gtt_mem_mapping *mapping;
+       int ret;
+
+       ret = psb_gtt_mm_alloc_insert_ht(mm, tgid, &hentry);
+       if (ret) {
+               DRM_DEBUG("alloc_insert failed\n");
+               return ret;
+       }
+
+       ret = psb_gtt_mm_alloc_insert_mem_mapping(mm,
+                       &hentry->ht,
+                       key,
+                       node,
+                       &mapping);
+       if (ret) {
+               DRM_DEBUG("mapping alloc_insert failed\n");
+               return ret;
+       }
+
+       *entry = mapping;
+
+       return 0;
+}
+
+static int psb_gtt_remove_node(struct psb_gtt_mm *mm,
+                              u32 tgid,
+                              u32 key,
+                              struct drm_mm_node **node)
+{
+       struct psb_gtt_hash_entry *hentry;
+       struct drm_mm_node *tmp;
+       int ret;
+
+       spin_lock(&mm->lock);
+       ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
+       if (ret) {
+               DRM_DEBUG("Cannot find entry for pid %u\n", tgid);
+               spin_unlock(&mm->lock);
+               return ret;
+       }
+       spin_unlock(&mm->lock);
+
+       /*remove mapping entry*/
+       spin_lock(&mm->lock);
+       ret = psb_gtt_mm_remove_free_mem_mapping_locked(&hentry->ht,
+                       key,
+                       &tmp);
+       if (ret) {
+               DRM_DEBUG("remove_free failed\n");
+               spin_unlock(&mm->lock);
+               return ret;
+       }
+
+       *node = tmp;
+
+       /*check the count of mapping entry*/
+       if (!hentry->count) {
+               DRM_DEBUG("count of mapping entry is zero, tgid=%u\n", tgid);
+               psb_gtt_mm_remove_free_ht_locked(mm, tgid);
+       }
+
+       spin_unlock(&mm->lock);
+
+       return 0;
+}
+
+static int psb_gtt_mm_alloc_mem(struct psb_gtt_mm *mm,
+                               uint32_t pages,
+                               uint32_t align,
+                               struct drm_mm_node **node)
+{
+       struct drm_mm_node *tmp_node;
+       int ret;
+
+       do {
+               ret = drm_mm_pre_get(&mm->base);
+               if (unlikely(ret)) {
+                       DRM_DEBUG("drm_mm_pre_get error\n");
+                       return ret;
+               }
+
+               spin_lock(&mm->lock);
+               tmp_node = drm_mm_search_free(&mm->base, pages, align, 1);
+               if (unlikely(!tmp_node)) {
+                       DRM_DEBUG("No free node found\n");
+                       spin_unlock(&mm->lock);
+                       break;
+               }
+
+               tmp_node = drm_mm_get_block_atomic(tmp_node, pages, align);
+               spin_unlock(&mm->lock);
+       } while (!tmp_node);
+
+       if (!tmp_node) {
+               DRM_DEBUG("Node allocation failed\n");
+               return -ENOMEM;
+       }
+
+       *node = tmp_node;
+       return 0;
+}
+
+static void psb_gtt_mm_free_mem(struct psb_gtt_mm *mm, struct drm_mm_node *node)
+{
+       spin_lock(&mm->lock);
+       drm_mm_put_block(node);
+       spin_unlock(&mm->lock);
+}
+
+int psb_gtt_map_meminfo(struct drm_device *dev,
+                       IMG_HANDLE hKernelMemInfo,
+                       uint32_t *offset)
+{
+       struct drm_psb_private *dev_priv
+       = (struct drm_psb_private *)dev->dev_private;
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+       struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+       struct psb_gtt *pg = dev_priv->pg;
+       uint32_t size, pages, offset_pages;
+       void *kmem;
+       struct drm_mm_node *node;
+       struct page **page_list;
+       struct psb_gtt_mem_mapping *mapping = NULL;
+       int ret;
+
+       ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+       if (ret) {
+               DRM_DEBUG("Cannot find kernelMemInfo handle %p\n",
+                         hKernelMemInfo);
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("Got psKernelMemInfo %p for handle %p\n",
+               psKernelMemInfo, hKernelMemInfo);
+
+       size = psKernelMemInfo->ui32AllocSize;
+       kmem = psKernelMemInfo->pvLinAddrKM;
+       pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+       DRM_DEBUG("KerMemInfo size %u, cpuVadr %p, pages %u, osMemHdl %p\n",
+                 size, kmem, pages, psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+       if (!kmem)
+               DRM_DEBUG("kmem is NULL");
+
+       /*get pages*/
+       ret = psb_get_pages_by_mem_handle(psKernelMemInfo->sMemBlk.hOSMemHandle,
+                                         &page_list);
+       if (ret) {
+               DRM_DEBUG("get pages error\n");
+               return ret;
+       }
+
+       DRM_DEBUG("get %u pages\n", pages);
+
+       /*alloc memory in TT apeture*/
+       ret = psb_gtt_mm_alloc_mem(mm, pages, 0, &node);
+       if (ret) {
+               DRM_DEBUG("alloc TT memory error\n");
+               goto failed_pages_alloc;
+       }
+
+       /*update psb_gtt_mm*/
+       ret = psb_gtt_add_node(mm,
+                              (u32)psb_get_tgid(),
+                              (u32)hKernelMemInfo,
+                              node,
+                              &mapping);
+       if (ret) {
+               DRM_DEBUG("add_node failed");
+               goto failed_add_node;
+       }
+
+       node = mapping->node;
+       offset_pages = node->start;
+
+       DRM_DEBUG("get free node for %u pages, offset %u pages",
+                 pages, offset_pages);
+
+       /*update gtt*/
+       psb_gtt_insert_pages(pg, page_list,
+                            (unsigned)offset_pages,
+                            (unsigned)pages,
+                            0,
+                            0,
+                            0);
+
+       *offset = offset_pages;
+       return 0;
+
+failed_add_node:
+       psb_gtt_mm_free_mem(mm, node);
+failed_pages_alloc:
+       kfree(page_list);
+       return ret;
+}
+
+int psb_gtt_unmap_meminfo(struct drm_device *dev, IMG_HANDLE hKernelMemInfo)
+{
+       struct drm_psb_private *dev_priv
+       = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+       struct psb_gtt *pg = dev_priv->pg;
+       uint32_t pages, offset_pages;
+       struct drm_mm_node *node;
+       int ret;
+
+       ret = psb_gtt_remove_node(mm,
+                                 (u32)psb_get_tgid(),
+                                 (u32)hKernelMemInfo,
+                                 &node);
+       if (ret) {
+               DRM_DEBUG("remove node failed\n");
+               return ret;
+       }
+
+       /*remove gtt entries*/
+       offset_pages = node->start;
+       pages = node->size;
+
+       psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
+
+
+       /*free tt node*/
+
+       psb_gtt_mm_free_mem(mm, node);
+       return 0;
+}
+
+int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       struct psb_gtt_mapping_arg *arg
+       = (struct psb_gtt_mapping_arg *)data;
+       uint32_t *offset_pages = &arg->offset_pages;
+
+       DRM_DEBUG("\n");
+
+       return psb_gtt_map_meminfo(dev, arg->hKernelMemInfo, offset_pages);
+}
+
+int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+
+       struct psb_gtt_mapping_arg *arg
+       = (struct psb_gtt_mapping_arg *)data;
+
+       DRM_DEBUG("\n");
+
+       return psb_gtt_unmap_meminfo(dev, arg->hKernelMemInfo);
+}
+
+int psb_gtt_map_pvr_memory(struct drm_device *dev,
+                          unsigned int hHandle,
+                          unsigned int ui32TaskId,
+                          IMG_CPU_PHYADDR *pPages,
+                          unsigned int ui32PagesNum,
+                          unsigned int *ui32Offset)
+{
+       struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt_mm * mm = dev_priv->gtt_mm;
+       struct psb_gtt * pg = dev_priv->pg;
+
+       uint32_t size, pages, offset_pages;
+       struct drm_mm_node * node = NULL;
+       struct psb_gtt_mem_mapping * mapping = NULL;
+       int ret;
+
+       size = ui32PagesNum * PAGE_SIZE;
+       pages = 0;
+
+       /*alloc memory in TT apeture*/
+       ret = psb_gtt_mm_alloc_mem(mm, ui32PagesNum, 0, &node);
+       if (ret) {
+               DRM_DEBUG("alloc TT memory error\n");
+               goto failed_pages_alloc;
+       }
+
+       /*update psb_gtt_mm*/
+       ret = psb_gtt_add_node(mm,
+                              (u32)ui32TaskId,
+                              (u32)hHandle,
+                              node,
+                              &mapping);
+       if (ret) {
+               DRM_DEBUG("add_node failed");
+               goto failed_add_node;
+       }
+
+       node = mapping->node;
+       offset_pages = node->start;
+
+       DRM_DEBUG("get free node for %u pages, offset %u pages", pages, offset_pages);
+
+       /*update gtt*/
+       psb_gtt_insert_phys_addresses(pg, pPages, (unsigned)offset_pages, (unsigned)ui32PagesNum, 0);
+
+       *ui32Offset = offset_pages;
+       return 0;
+
+failed_add_node:
+       psb_gtt_mm_free_mem(mm, node);
+failed_pages_alloc:
+       return ret;
+}
+
+
+int psb_gtt_unmap_pvr_memory(struct drm_device *dev, unsigned int hHandle, unsigned int ui32TaskId)
+{
+       struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt_mm * mm = dev_priv->gtt_mm;
+       struct psb_gtt * pg = dev_priv->pg;
+       uint32_t pages, offset_pages;
+       struct drm_mm_node * node;
+       int ret;
+
+       ret = psb_gtt_remove_node(mm,
+                                 (u32)ui32TaskId,
+                                 (u32)hHandle,
+                                 &node);
+       if (ret) {
+               printk("remove node failed\n");
+               return ret;
+       }
+
+       /*remove gtt entries*/
+       offset_pages = node->start;
+       pages = node->size;
+
+       psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
+
+       /*free tt node*/
+       psb_gtt_mm_free_mem(mm, node);
+       return 0;
+}
diff --git a/drivers/staging/mrst/drv/psb_gtt.h b/drivers/staging/mrst/drv/psb_gtt.h
new file mode 100644 (file)
index 0000000..9dda0d4
--- /dev/null
@@ -0,0 +1,112 @@
+/**************************************************************************
+ * Copyright (c) 2007-2008, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_GTT_H_
+#define _PSB_GTT_H_
+
+#include <drm/drmP.h>
+
+#include "img_types.h"
+
+struct psb_gtt {
+       struct drm_device *dev;
+       int initialized;
+       uint32_t gatt_start;
+       uint32_t mmu_gatt_start;
+       uint32_t ci_start;
+       uint32_t rar_start;
+       uint32_t gtt_start;
+       uint32_t gtt_phys_start;
+       unsigned gtt_pages;
+       unsigned gatt_pages;
+       uint32_t stolen_base;
+       void __iomem *vram_addr;
+       uint32_t pge_ctl;
+       u16 gmch_ctrl;
+       unsigned long stolen_size;
+       unsigned long vram_stolen_size;
+       unsigned long ci_stolen_size;
+       unsigned long rar_stolen_size;
+       uint32_t __iomem *gtt_map;
+       struct rw_semaphore sem;
+};
+
+struct psb_gtt_mm {
+       struct drm_mm base;
+       struct drm_open_hash hash;
+       uint32_t count;
+       spinlock_t lock;
+};
+
+struct psb_gtt_hash_entry {
+       struct drm_open_hash ht;
+       uint32_t count;
+       struct drm_hash_item item;
+};
+
+struct psb_gtt_mem_mapping {
+       struct drm_mm_node *node;
+       struct drm_hash_item item;
+};
+
+#if 0
+/*Ioctl args*/
+struct psb_gtt_mapping_arg {
+       IMG_HANDLE hKernelMemInfo;
+};
+#endif
+
+/*Exported functions*/
+extern int psb_gtt_init(struct psb_gtt *pg, int resume);
+extern int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
+                               unsigned offset_pages, unsigned num_pages,
+                               unsigned desired_tile_stride,
+                               unsigned hw_tile_stride, int type);
+extern int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages,
+                               unsigned num_pages,
+                               unsigned desired_tile_stride,
+                               unsigned hw_tile_stride,
+                               int rc_prot);
+
+extern struct psb_gtt *psb_gtt_alloc(struct drm_device *dev);
+extern void psb_gtt_takedown(struct psb_gtt *pg, int free);
+extern int psb_gtt_map_meminfo(struct drm_device *dev,
+                               IMG_HANDLE hKernelMemInfo,
+                               uint32_t *offset);
+extern int psb_gtt_unmap_meminfo(struct drm_device *dev,
+                                IMG_HANDLE hKernelMemInfo);
+extern int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data,
+                                    struct drm_file *file_priv);
+extern int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data,
+                                      struct drm_file *file_priv);
+extern int psb_gtt_mm_init(struct psb_gtt *pg);
+extern void psb_gtt_mm_takedown(void);
+
+extern int psb_gtt_map_pvr_memory(struct drm_device *dev,
+                                                                  unsigned int hHandle,
+                                                                  unsigned int ui32TaskId,
+                                                                  IMG_CPU_PHYADDR *pPages,
+                                                                  unsigned int ui32PagesNum,
+                                                                  unsigned int *ui32Offset);
+
+extern int psb_gtt_unmap_pvr_memory(struct drm_device *dev,
+                                                                        unsigned int hHandle,
+                                                                        unsigned int ui32TaskId);
+
+#endif
diff --git a/drivers/staging/mrst/drv/psb_hotplug.c b/drivers/staging/mrst/drv/psb_hotplug.c
new file mode 100644 (file)
index 0000000..3f41362
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+
+#include "psb_umevents.h"
+#include "psb_hotplug.h"
+/**
+ * inform the kernel of the work to be performed and related function.
+ *
+ */
+static DECLARE_WORK(hotplug_dev_create_work, &psb_hotplug_dev_create_wq);
+static DECLARE_WORK(hotplug_dev_remove_work, &psb_hotplug_dev_remove_wq);
+static DECLARE_WORK(hotplug_dev_change_work, &psb_hotplug_dev_change_wq);
+/**
+ * psb_hotplug_notify_change_um - notify user mode of hotplug changes
+ *
+ * @name: name of event to notify user mode of change to
+ * @state: hotplug state to search for event object in
+ *
+ */
+int psb_hotplug_notify_change_um(const char *name,
+                            struct hotplug_state *state)
+{
+       strcpy(&(state->hotplug_change_wq_data.dev_name_arry
+                [state->hotplug_change_wq_data.dev_name_write][0]), name);
+       state->hotplug_change_wq_data.dev_name_arry_rw_status
+               [state->hotplug_change_wq_data.dev_name_write] =
+               DRM_HOTPLUG_READY_TO_READ;
+       if (state->hotplug_change_wq_data.dev_name_read_write_wrap_ack == 1)
+               state->hotplug_change_wq_data.dev_name_read_write_wrap_ack = 0;
+       state->hotplug_change_wq_data.dev_name_write++;
+       if (state->hotplug_change_wq_data.dev_name_write ==
+          state->hotplug_change_wq_data.dev_name_read) {
+               state->hotplug_change_wq_data.dev_name_write--;
+               return IRQ_NONE;
+       }
+       if (state->hotplug_change_wq_data.dev_name_write >
+          DRM_HOTPLUG_RING_DEPTH_MAX) {
+               state->hotplug_change_wq_data.dev_name_write = 0;
+               state->hotplug_change_wq_data.dev_name_write_wrap = 1;
+       }
+       state->hotplug_change_wq_data.hotplug_dev_list = state->list;
+       queue_work(state->hotplug_wq, &(state->hotplug_change_wq_data.work));
+       return IRQ_HANDLED;
+}
+/**
+ *
+ * psb_hotplug_create_and_notify_um - create and notify user mode of new dev
+ *
+ * @name: name to give for new event / device
+ * @state: hotplug state to track new event /device in
+ *
+ */
+int psb_hotplug_create_and_notify_um(const char *name,
+                                struct hotplug_state *state)
+{
+       strcpy(&(state->hotplug_create_wq_data.dev_name_arry
+                [state->hotplug_create_wq_data.dev_name_write][0]), name);
+       state->hotplug_create_wq_data.dev_name_arry_rw_status
+               [state->hotplug_create_wq_data.dev_name_write] =
+               DRM_HOTPLUG_READY_TO_READ;
+       if (state->hotplug_create_wq_data.dev_name_read_write_wrap_ack == 1)
+               state->hotplug_create_wq_data.dev_name_read_write_wrap_ack = 0;
+       state->hotplug_create_wq_data.dev_name_write++;
+       if (state->hotplug_create_wq_data.dev_name_write ==
+          state->hotplug_create_wq_data.dev_name_read) {
+               state->hotplug_create_wq_data.dev_name_write--;
+               return IRQ_NONE;
+       }
+       if (state->hotplug_create_wq_data.dev_name_write >
+          DRM_HOTPLUG_RING_DEPTH_MAX) {
+               state->hotplug_create_wq_data.dev_name_write = 0;
+               state->hotplug_create_wq_data.dev_name_write_wrap = 1;
+       }
+       state->hotplug_create_wq_data.hotplug_dev_list = state->list;
+       queue_work(state->hotplug_wq, &(state->hotplug_create_wq_data.work));
+       return IRQ_HANDLED;
+}
+/*EXPORT_SYMBOL(psb_hotplug_create_and_notify_um); */
+/**
+ * psb_hotplug_remove_and_notify_um - remove device and notify user mode
+ *
+ * @name: name of event / device to remove
+ * @state: hotplug state to remove event / device from
+ *
+ */
+int psb_hotplug_remove_and_notify_um(const char *name,
+                                struct hotplug_state *state)
+{
+       strcpy(&(state->hotplug_remove_wq_data.dev_name_arry
+                [state->hotplug_remove_wq_data.dev_name_write][0]), name);
+       state->hotplug_remove_wq_data.dev_name_arry_rw_status
+               [state->hotplug_remove_wq_data.dev_name_write] =
+               DRM_HOTPLUG_READY_TO_READ;
+       if (state->hotplug_remove_wq_data.dev_name_read_write_wrap_ack == 1)
+               state->hotplug_remove_wq_data.dev_name_read_write_wrap_ack = 0;
+       state->hotplug_remove_wq_data.dev_name_write++;
+       if (state->hotplug_remove_wq_data.dev_name_write ==
+          state->hotplug_remove_wq_data.dev_name_read) {
+               state->hotplug_remove_wq_data.dev_name_write--;
+               return IRQ_NONE;
+       }
+       if (state->hotplug_remove_wq_data.dev_name_write >
+          DRM_HOTPLUG_RING_DEPTH_MAX) {
+               state->hotplug_remove_wq_data.dev_name_write = 0;
+               state->hotplug_remove_wq_data.dev_name_write_wrap = 1;
+       }
+       state->hotplug_remove_wq_data.hotplug_dev_list = state->list;
+       queue_work(state->hotplug_wq, &(state->hotplug_remove_wq_data.work));
+       return IRQ_HANDLED;
+}
+/*EXPORT_SYMBOL(psb_hotplug_remove_and_notify_um); */
+/**
+ * psb_hotplug_device_pool_create_and_init - make new hotplug device pool
+ *
+ * @parent_kobj: parent kobject to associate hotplug kset with
+ * @state: hotplug state to assocaite workqueues with
+ *
+ */
+struct umevent_list *psb_hotplug_device_pool_create_and_init(
+                                    struct kobject *parent_kobj,
+                                    struct hotplug_state *state)
+{
+       struct umevent_list *new_hotplug_dev_list = NULL;
+
+       new_hotplug_dev_list = psb_umevent_create_list();
+       if (new_hotplug_dev_list)
+               psb_umevent_init(parent_kobj, new_hotplug_dev_list,
+                                "psb_hotplug");
+
+       state->hotplug_wq = create_singlethread_workqueue("hotplug-wq");
+       if (!state->hotplug_wq)
+               return NULL;
+
+       INIT_WORK(&state->hotplug_create_wq_data.work,
+                 psb_hotplug_dev_create_wq);
+       INIT_WORK(&state->hotplug_remove_wq_data.work,
+                 psb_hotplug_dev_remove_wq);
+       INIT_WORK(&state->hotplug_change_wq_data.work,
+                 psb_hotplug_dev_change_wq);
+
+       state->hotplug_create_wq_data.dev_name_read = 0;
+       state->hotplug_create_wq_data.dev_name_write = 0;
+       state->hotplug_create_wq_data.dev_name_write_wrap = 0;
+       state->hotplug_create_wq_data.dev_name_read_write_wrap_ack = 0;
+       memset(&(state->hotplug_create_wq_data.dev_name_arry_rw_status[0]),
+              0, sizeof(int)*DRM_HOTPLUG_RING_DEPTH);
+
+       state->hotplug_remove_wq_data.dev_name_read = 0;
+       state->hotplug_remove_wq_data.dev_name_write = 0;
+       state->hotplug_remove_wq_data.dev_name_write_wrap = 0;
+       state->hotplug_remove_wq_data.dev_name_read_write_wrap_ack = 0;
+       memset(&(state->hotplug_remove_wq_data.dev_name_arry_rw_status[0]),
+              0, sizeof(int)*DRM_HOTPLUG_RING_DEPTH);
+
+       state->hotplug_change_wq_data.dev_name_read = 0;
+       state->hotplug_change_wq_data.dev_name_write = 0;
+       state->hotplug_change_wq_data.dev_name_write_wrap = 0;
+       state->hotplug_change_wq_data.dev_name_read_write_wrap_ack = 0;
+       memset(&(state->hotplug_change_wq_data.dev_name_arry_rw_status[0]),
+              0, sizeof(int)*DRM_HOTPLUG_RING_DEPTH);
+
+       return new_hotplug_dev_list;
+}
+/*EXPORT_SYMBOL(psb_hotplug_device_pool_create_and_init); */
+/**
+ *
+ * psb_hotplug_init - init hotplug subsystem
+ *
+ * @parent_kobj: parent kobject to associate hotplug state with
+ *
+ */
+struct hotplug_state *psb_hotplug_init(struct kobject *parent_kobj)
+{
+       struct hotplug_state *state;
+       state = kzalloc(sizeof(struct hotplug_state), GFP_KERNEL);
+
+       if (!state)
+               return state;
+
+       state->list = NULL;
+       state->list = psb_hotplug_device_pool_create_and_init(
+                                                     parent_kobj,
+                                                     state);
+
+       psb_hotplug_create_and_notify_um("hpd_hdmi", state);
+
+       return state;
+}
+/**
+ * psb_hotplug_device_pool_destroy - destroy all hotplug related resources
+ *
+ * @state: hotplug state to destroy
+ *
+ */
+void psb_hotplug_device_pool_destroy(struct hotplug_state *state)
+{
+       flush_workqueue(state->hotplug_wq);
+       destroy_workqueue(state->hotplug_wq);
+       psb_umevent_cleanup(state->list);
+       kfree(state);
+}
+/*EXPORT_SYMBOL(psb_hotplug_device_pool_destroy); */
+/**
+ * psb_hotplug_dev_create_wq - create workqueue implementation
+ *
+ * @work: work struct to use for kernel scheduling
+ *
+ */
+void psb_hotplug_dev_create_wq(struct work_struct *work)
+{
+       struct hotplug_disp_workqueue_data *wq_data;
+       struct umevent_obj *wq_working_hotplug_disp_obj;
+       wq_data = to_hotplug_disp_workqueue_data(work);
+       if (wq_data->dev_name_write_wrap == 1) {
+               wq_data->dev_name_read_write_wrap_ack = 1;
+               wq_data->dev_name_write_wrap = 0;
+               while (wq_data->dev_name_read != DRM_HOTPLUG_RING_DEPTH_MAX) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               wq_working_hotplug_disp_obj =
+                               psb_create_umevent_obj(
+                                       &wq_data->dev_name_arry
+                                       [wq_data->dev_name_read][0],
+                                       wq_data->hotplug_dev_list);
+                               wq_data->dev_name_arry_rw_status
+                                       [wq_data->dev_name_read] =
+                                       DRM_HOTPLUG_READ_COMPLETE;
+                               /* psb_umevent_notify
+                                       (wq_working_hotplug_disp_obj);*/
+                       }
+                       wq_data->dev_name_read++;
+               }
+               wq_data->dev_name_read = 0;
+               while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               wq_working_hotplug_disp_obj =
+                               psb_create_umevent_obj(
+                                       &wq_data->dev_name_arry
+                                       [wq_data->dev_name_read][0],
+                                       wq_data->hotplug_dev_list);
+                               wq_data->dev_name_arry_rw_status
+                                       [wq_data->dev_name_read] =
+                                       DRM_HOTPLUG_READ_COMPLETE;
+                               /*psb_umevent_notify
+                                       (wq_working_hotplug_disp_obj);*/
+                       }
+                       wq_data->dev_name_read++;
+               }
+       } else {
+               while (wq_data->dev_name_read < wq_data->dev_name_write) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               wq_working_hotplug_disp_obj =
+                               psb_create_umevent_obj(
+                               &wq_data->dev_name_arry
+                                       [wq_data->dev_name_read][0],
+                                       wq_data->hotplug_dev_list);
+                               wq_data->dev_name_arry_rw_status
+                                       [wq_data->dev_name_read] =
+                                       DRM_HOTPLUG_READ_COMPLETE;
+                               /*psb_umevent_notify
+                                       (wq_working_hotplug_disp_obj);*/
+                       }
+                       wq_data->dev_name_read++;
+               }
+       }
+       if (wq_data->dev_name_read > DRM_HOTPLUG_RING_DEPTH_MAX)
+               wq_data->dev_name_read = 0;
+}
+/*EXPORT_SYMBOL(psb_hotplug_dev_create_wq); */
+/**
+ * psb_hotplug_dev_remove_wq - remove workqueue implementation
+ *
+ * @work: work struct to use for kernel scheduling
+ *
+ */
+void psb_hotplug_dev_remove_wq(struct work_struct *work)
+{
+       struct hotplug_disp_workqueue_data *wq_data;
+       wq_data = to_hotplug_disp_workqueue_data(work);
+       if (wq_data->dev_name_write_wrap == 1) {
+               wq_data->dev_name_read_write_wrap_ack = 1;
+               wq_data->dev_name_write_wrap = 0;
+               while (wq_data->dev_name_read != DRM_HOTPLUG_RING_DEPTH_MAX) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               psb_umevent_remove_from_list(
+                               wq_data->hotplug_dev_list,
+                               &wq_data->dev_name_arry
+                               [wq_data->dev_name_read][0]);
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                               DRM_HOTPLUG_READ_COMPLETE;
+                       }
+                       wq_data->dev_name_read++;
+               }
+               wq_data->dev_name_read = 0;
+               while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               psb_umevent_remove_from_list(
+                               wq_data->hotplug_dev_list,
+                               &wq_data->dev_name_arry
+                               [wq_data->dev_name_read][0]);
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                               DRM_HOTPLUG_READ_COMPLETE;
+                       }
+                       wq_data->dev_name_read++;
+               }
+       } else {
+               while (wq_data->dev_name_read < wq_data->dev_name_write) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               psb_umevent_remove_from_list(
+                               wq_data->hotplug_dev_list,
+                               &wq_data->dev_name_arry
+                               [wq_data->dev_name_read][0]);
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                               DRM_HOTPLUG_READ_COMPLETE;
+                       }
+                       wq_data->dev_name_read++;
+               }
+       }
+       if (wq_data->dev_name_read > DRM_HOTPLUG_RING_DEPTH_MAX)
+               wq_data->dev_name_read = 0;
+}
+/*EXPORT_SYMBOL(psb_hotplug_dev_remove_wq); */
+/**
+ * psb_hotplug_dev_change_wq - change workqueue implementation
+ *
+ * @work: work struct to use for kernel scheduling
+ *
+ */
+void psb_hotplug_dev_change_wq(struct work_struct *work)
+{
+       struct hotplug_disp_workqueue_data *wq_data;
+       struct umevent_obj *wq_working_hotplug_disp_obj;
+       wq_data = to_hotplug_disp_workqueue_data(work);
+       if (wq_data->dev_name_write_wrap == 1) {
+               wq_data->dev_name_read_write_wrap_ack = 1;
+               wq_data->dev_name_write_wrap = 0;
+               while (wq_data->dev_name_read != DRM_HOTPLUG_RING_DEPTH_MAX) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                               DRM_HOTPLUG_READ_COMPLETE;
+
+                               wq_working_hotplug_disp_obj =
+                                       psb_umevent_find_obj(
+                                            &wq_data->dev_name_arry
+                                            [wq_data->dev_name_read][0],
+                                             wq_data->hotplug_dev_list);
+                               psb_umevent_notify_change_gfxsock
+                                       (wq_working_hotplug_disp_obj,
+                                        DRM_HOTPLUG_SOCKET_GROUP_ID);
+                       }
+                       wq_data->dev_name_read++;
+               }
+               wq_data->dev_name_read = 0;
+               while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                               DRM_HOTPLUG_READ_COMPLETE;
+
+                               wq_working_hotplug_disp_obj =
+                                       psb_umevent_find_obj(
+                                            &wq_data->dev_name_arry
+                                            [wq_data->dev_name_read][0],
+                                             wq_data->hotplug_dev_list);
+                               psb_umevent_notify_change_gfxsock
+                                       (wq_working_hotplug_disp_obj,
+                                        DRM_HOTPLUG_SOCKET_GROUP_ID);
+                       }
+                       wq_data->dev_name_read++;
+               }
+       } else {
+               while (wq_data->dev_name_read < wq_data->dev_name_write) {
+                       if (wq_data->dev_name_arry_rw_status
+                          [wq_data->dev_name_read] ==
+                          DRM_HOTPLUG_READY_TO_READ) {
+                               wq_data->dev_name_arry_rw_status
+                               [wq_data->dev_name_read] =
+                                       DRM_HOTPLUG_READ_COMPLETE;
+
+                               wq_working_hotplug_disp_obj =
+                                       psb_umevent_find_obj(
+                                            &wq_data->dev_name_arry
+                                            [wq_data->dev_name_read][0],
+                                             wq_data->hotplug_dev_list);
+                               psb_umevent_notify_change_gfxsock
+                                       (wq_working_hotplug_disp_obj,
+                                        DRM_HOTPLUG_SOCKET_GROUP_ID);
+                       }
+                       wq_data->dev_name_read++;
+               }
+       }
+       if (wq_data->dev_name_read > DRM_HOTPLUG_RING_DEPTH_MAX)
+               wq_data->dev_name_read = 0;
+}
+/*EXPORT_SYMBOL(psb_hotplug_dev_change_wq); */
diff --git a/drivers/staging/mrst/drv/psb_hotplug.h b/drivers/staging/mrst/drv/psb_hotplug.h
new file mode 100644 (file)
index 0000000..b6e42a4
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+#ifndef _PSB_HOTPLUG_H_
+#define _PSB_HOTPLUG_H_
+/**
+ * required includes
+ *
+ */
+#include "psb_umevents.h"
+/**
+ * hotplug specific defines
+ *
+ */
+#define DRM_HOTPLUG_RING_DEPTH 256
+#define DRM_HOTPLUG_RING_DEPTH_MAX (DRM_HOTPLUG_RING_DEPTH-1)
+#define DRM_HOTPLUG_READY_TO_READ 1
+#define DRM_HOTPLUG_READ_COMPLETE 2
+/**
+ * hotplug workqueue data struct.
+ */
+struct hotplug_disp_workqueue_data {
+       struct work_struct work;
+       const char *dev_name;
+       int dev_name_write;
+       int dev_name_read;
+       int dev_name_write_wrap;
+       int dev_name_read_write_wrap_ack;
+       char dev_name_arry[DRM_HOTPLUG_RING_DEPTH][24];
+       int dev_name_arry_rw_status[DRM_HOTPLUG_RING_DEPTH];
+       struct umevent_list *hotplug_dev_list;
+};
+/**
+ * hotplug state structure
+ *
+ */
+struct hotplug_state {
+       struct workqueue_struct *hotplug_wq;
+       struct hotplug_disp_workqueue_data hotplug_remove_wq_data;
+       struct hotplug_disp_workqueue_data hotplug_create_wq_data;
+       struct hotplug_disp_workqueue_data hotplug_change_wq_data;
+       struct umevent_list *list;
+};
+/**
+ * main interface function prototytpes for hotplug support.
+ *
+ */
+struct hotplug_state *psb_hotplug_init(struct kobject *parent_kobj);
+extern int psb_hotplug_notify_change_um(const char *name,
+                                   struct hotplug_state *state);
+extern int psb_hotplug_create_and_notify_um(const char *name,
+                                       struct hotplug_state *state);
+extern int psb_hotplug_remove_and_notify_um(const char *name,
+                                       struct hotplug_state *state);
+extern struct umevent_list *psb_hotplug_device_pool_create_and_init(
+                                           struct kobject *parent_kobj,
+                                           struct hotplug_state *state);
+extern void psb_hotplug_device_pool_destroy(struct hotplug_state *state);
+/**
+ * to go back and forth between work strauct and workqueue data
+ *
+ */
+#define to_hotplug_disp_workqueue_data(x) \
+       container_of(x, struct hotplug_disp_workqueue_data, work)
+
+/**
+ * function prototypes for workqueue implementation
+ *
+ */
+extern void psb_hotplug_dev_create_wq(struct work_struct *work);
+extern void psb_hotplug_dev_remove_wq(struct work_struct *work);
+extern void psb_hotplug_dev_change_wq(struct work_struct *work);
+#endif
diff --git a/drivers/staging/mrst/drv/psb_intel_display.c b/drivers/staging/mrst/drv/psb_intel_display.c
new file mode 100644 (file)
index 0000000..fc4a74f
--- /dev/null
@@ -0,0 +1,1930 @@
+/*
+ * Copyright Ã‚© 2006-2007 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *     Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drmP.h>
+#include "psb_fb.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_display.h"
+#include "psb_page_flip.h"
+#include "psb_powermgmt.h"
+#include "mdfld_output.h"
+
+static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
+                               struct drm_framebuffer *old_fb);
+static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
+                             struct drm_display_mode *mode,
+                             struct drm_display_mode *adjusted_mode,
+                             int x, int y,
+                             struct drm_framebuffer *old_fb);
+static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode);
+
+struct psb_intel_clock_t {
+       /* given values */
+       int n;
+       int m1, m2;
+       int p1, p2;
+       /* derived values */
+       int dot;
+       int vco;
+       int m;
+       int p;
+};
+
+struct psb_intel_range_t {
+       int min, max;
+};
+
+/**
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_connector *l_entry;
+
+       list_for_each_entry(l_entry, &mode_config->connector_list, head) {
+               if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
+                       struct psb_intel_output *psb_intel_output =
+                           to_psb_intel_output(l_entry);
+                       if (psb_intel_output->type == type)
+                               return true;
+               }
+       }
+       return false;
+}
+
+void psb_intel_wait_for_vblank(struct drm_device *dev)
+{
+       /* Wait for 20ms, i.e. one cycle at 50hz. */
+       mdelay(20);
+}
+
+static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
+{
+       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void psb_intel_crtc_commit(struct drm_crtc *crtc)
+{
+       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+void psb_intel_encoder_prepare(struct drm_encoder *encoder)
+{
+       struct drm_encoder_helper_funcs *encoder_funcs =
+           encoder->helper_private;
+       /* lvds has its own version of prepare see psb_intel_lvds_prepare */
+       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+void psb_intel_encoder_commit(struct drm_encoder *encoder)
+{
+       struct drm_encoder_helper_funcs *encoder_funcs =
+           encoder->helper_private;
+       /* lvds has its own version of commit see psb_intel_lvds_commit */
+       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
+                                 struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
+{
+       u32 pfit_control;
+
+       /* i830 doesn't have a panel fitter */
+       if (IS_I830(dev))
+               return -1;
+
+       pfit_control = REG_READ(PFIT_CONTROL);
+
+       /* See if the panel fitter is in use */
+       if ((pfit_control & PFIT_ENABLE) == 0)
+               return -1;
+
+       /* 965 can place panel fitter on either pipe */
+       return (pfit_control >> 29) & 0x3;
+}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv =
+                               (struct drm_psb_private *)dev->dev_private;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       int palreg = PALETTE_A;
+       int i;
+
+       /* The clocks have to be on to load the palette. */
+       if (!crtc->enabled)
+               return;
+
+       switch (psb_intel_crtc->pipe) {
+       case 0:
+               break;
+       case 1:
+               palreg = PALETTE_B;
+               break;
+       case 2:
+               palreg = PALETTE_C;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return;
+       }
+       
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                     OSPM_UHB_ONLY_IF_ON)) {
+               for (i = 0; i < 256; i++) {
+                       REG_WRITE(palreg + 4 * i,
+                                 ((psb_intel_crtc->lut_r[i] +
+                                 psb_intel_crtc->lut_adj[i]) << 16) |
+                                 ((psb_intel_crtc->lut_g[i] +
+                                 psb_intel_crtc->lut_adj[i]) << 8) |
+                                 (psb_intel_crtc->lut_b[i] +
+                                 psb_intel_crtc->lut_adj[i]));
+               }
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       } else {
+               for (i = 0; i < 256; i++) {
+                       dev_priv->save_palette_a[i] =
+                                 ((psb_intel_crtc->lut_r[i] +
+                                 psb_intel_crtc->lut_adj[i]) << 16) |
+                                 ((psb_intel_crtc->lut_g[i] +
+                                 psb_intel_crtc->lut_adj[i]) << 8) |
+                                 (psb_intel_crtc->lut_b[i] +
+                                 psb_intel_crtc->lut_adj[i]);
+               }
+
+       }
+}
+
+/**
+ * Save HW states of giving crtc
+ */
+static void psb_intel_crtc_save(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       /* struct drm_psb_private *dev_priv =
+                       (struct drm_psb_private *)dev->dev_private; */
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+       int pipeA = (psb_intel_crtc->pipe == 0);
+       uint32_t paletteReg;
+       int i;
+
+       DRM_DEBUG("\n");
+
+       if (!crtc_state) {
+               DRM_DEBUG("No CRTC state found\n");
+               return;
+       }
+
+       crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
+       crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
+       crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
+       crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
+       crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
+       crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
+       crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
+       crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
+       crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
+       crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
+       crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
+       crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
+       crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
+
+       /*NOTE: DSPSIZE DSPPOS only for psb*/
+       crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
+       crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
+
+       crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
+
+       DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+                       crtc_state->saveDSPCNTR,
+                       crtc_state->savePIPECONF,
+                       crtc_state->savePIPESRC,
+                       crtc_state->saveFP0,
+                       crtc_state->saveFP1,
+                       crtc_state->saveDPLL,
+                       crtc_state->saveHTOTAL,
+                       crtc_state->saveHBLANK,
+                       crtc_state->saveHSYNC,
+                       crtc_state->saveVTOTAL,
+                       crtc_state->saveVBLANK,
+                       crtc_state->saveVSYNC,
+                       crtc_state->saveDSPSTRIDE,
+                       crtc_state->saveDSPSIZE,
+                       crtc_state->saveDSPPOS,
+                       crtc_state->saveDSPBASE
+               );
+
+       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+       for (i = 0; i < 256; ++i)
+               crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
+}
+
+/**
+ * Restore HW states of giving crtc
+ */
+static void psb_intel_crtc_restore(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       /* struct drm_psb_private * dev_priv =
+                               (struct drm_psb_private *)dev->dev_private; */
+       struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
+       struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+       /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
+       int pipeA = (psb_intel_crtc->pipe == 0);
+       uint32_t paletteReg;
+       int i;
+
+       DRM_DEBUG("\n");
+
+       if (!crtc_state) {
+               DRM_DEBUG("No crtc state\n");
+               return;
+       }
+
+       DRM_DEBUG(
+               "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+               REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
+               REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
+               REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
+               REG_READ(pipeA ? FPA0 : FPB0),
+               REG_READ(pipeA ? FPA1 : FPB1),
+               REG_READ(pipeA ? DPLL_A : DPLL_B),
+               REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
+               REG_READ(pipeA ? HBLANK_A : HBLANK_B),
+               REG_READ(pipeA ? HSYNC_A : HSYNC_B),
+               REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
+               REG_READ(pipeA ? VBLANK_A : VBLANK_B),
+               REG_READ(pipeA ? VSYNC_A : VSYNC_B),
+               REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
+               REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
+               REG_READ(pipeA ? DSPAPOS : DSPBPOS),
+               REG_READ(pipeA ? DSPABASE : DSPBBASE)
+               );
+
+       DRM_DEBUG(
+               "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+               crtc_state->saveDSPCNTR,
+               crtc_state->savePIPECONF,
+               crtc_state->savePIPESRC,
+               crtc_state->saveFP0,
+               crtc_state->saveFP1,
+               crtc_state->saveDPLL,
+               crtc_state->saveHTOTAL,
+               crtc_state->saveHBLANK,
+               crtc_state->saveHSYNC,
+               crtc_state->saveVTOTAL,
+               crtc_state->saveVBLANK,
+               crtc_state->saveVSYNC,
+               crtc_state->saveDSPSTRIDE,
+               crtc_state->saveDSPSIZE,
+               crtc_state->saveDSPPOS,
+               crtc_state->saveDSPBASE
+               );
+
+       if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
+               REG_WRITE(pipeA ? DPLL_A : DPLL_B,
+                       crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
+               REG_READ(pipeA ? DPLL_A : DPLL_B);
+               DRM_DEBUG("write dpll: %x\n",
+                               REG_READ(pipeA ? DPLL_A : DPLL_B));
+               udelay(150);
+       }
+
+       REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
+       REG_READ(pipeA ? FPA0 : FPB0);
+
+       REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
+       REG_READ(pipeA ? FPA1 : FPB1);
+
+       REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
+       REG_READ(pipeA ? DPLL_A : DPLL_B);
+       udelay(150);
+
+       REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
+       REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
+       REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
+       REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
+       REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
+       REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
+       REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
+
+       REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
+       REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
+
+       REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
+       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+       REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
+
+       psb_intel_wait_for_vblank(dev);
+
+       REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
+       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+
+       psb_intel_wait_for_vblank(dev);
+
+       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+       for (i = 0; i < 256; ++i)
+               REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
+}
+
+/* FIXME: Start using the start and size parameters */
+static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+                               u16 *green, u16 *blue, uint32_t start,
+                               uint32_t size)
+{
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       int i;
+
+       if (size != 256)
+               return;
+
+       for (i = 0; i < 256; i++) {
+               psb_intel_crtc->lut_r[i] = red[i] >> 8;
+               psb_intel_crtc->lut_g[i] = green[i] >> 8;
+               psb_intel_crtc->lut_b[i] = blue[i] >> 8;
+       }
+
+       psb_intel_crtc_load_lut(crtc);
+}
+
+static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
+{
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+       kfree(psb_intel_crtc->crtc_state);
+       drm_crtc_cleanup(crtc);
+       kfree(psb_intel_crtc);
+}
+
+static const struct drm_crtc_helper_funcs mdfld_helper_funcs;
+static const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
+
+/*
+ * Set the default value of cursor control and base register
+ * to zero. This is a workaround for h/w defect on oaktrail
+ */
+static void psb_intel_cursor_init(struct drm_device *dev, int pipe)
+{
+       uint32_t control;
+       uint32_t base;
+
+       switch (pipe) {
+       case 0:
+               control = CURACNTR;
+               base = CURABASE;
+               break;
+       case 1:
+               control = CURBCNTR;
+               base = CURBBASE;
+               break;
+       case 2:
+               control = CURCCNTR;
+               base = CURCBASE;
+               break;
+       default:
+               return;
+       }
+
+       REG_WRITE(control, 0);
+       REG_WRITE(base, 0);
+}
+
+void psb_intel_crtc_init(struct drm_device *dev, int pipe,
+                    struct psb_intel_mode_device *mode_dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_crtc *psb_intel_crtc;
+       int i;
+       uint16_t *r_base, *g_base, *b_base;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       /* We allocate a extra array of drm_connector pointers
+        * for fbdev after the crtc */
+       psb_intel_crtc =
+           kzalloc(sizeof(struct psb_intel_crtc) +
+                   (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
+                   GFP_KERNEL);
+       if (psb_intel_crtc == NULL)
+               return;
+
+       psb_intel_crtc->crtc_state =
+               kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
+       if (!psb_intel_crtc->crtc_state) {
+               DRM_INFO("Crtc state error: No memory\n");
+               kfree(psb_intel_crtc);
+               return;
+       }
+
+       drm_crtc_init(dev, &psb_intel_crtc->base, &mdfld_intel_crtc_funcs);
+
+       drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
+       psb_intel_crtc->pipe = pipe;
+       psb_intel_crtc->plane = pipe;
+
+       r_base = psb_intel_crtc->base.gamma_store;
+       g_base = r_base + 256;
+       b_base = g_base + 256;
+       for (i = 0; i < 256; i++) {
+               psb_intel_crtc->lut_r[i] = i;
+               psb_intel_crtc->lut_g[i] = i;
+               psb_intel_crtc->lut_b[i] = i;
+               r_base[i] = i << 8;
+               g_base[i] = i << 8;
+               b_base[i] = i << 8;
+
+               psb_intel_crtc->lut_adj[i] = 0;
+       }
+
+       psb_intel_crtc->mode_dev = mode_dev;
+       psb_intel_crtc->cursor_addr = 0;
+
+       drm_crtc_helper_add(&psb_intel_crtc->base, &mdfld_helper_funcs);
+
+       /* Setup the array of drm_connector pointer array */
+       psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
+       BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
+              dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL);
+       dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = &psb_intel_crtc->base;
+       dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = &psb_intel_crtc->base;
+       psb_intel_crtc->mode_set.connectors =
+           (struct drm_connector **) (psb_intel_crtc + 1);
+       psb_intel_crtc->mode_set.num_connectors = 0;
+
+       psb_intel_cursor_init(dev, pipe);
+}
+
+int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
+       struct drm_mode_object *drmmode_obj;
+       struct psb_intel_crtc *crtc;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
+                       DRM_MODE_OBJECT_CRTC);
+
+       if (!drmmode_obj) {
+               DRM_ERROR("no such CRTC id\n");
+               return -EINVAL;
+       }
+
+       crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj));
+       pipe_from_crtc_id->pipe = crtc->pipe;
+
+       return 0;
+}
+
+int psb_intel_connector_clones(struct drm_device *dev, int type_mask)
+{
+       int index_mask = 0;
+       struct drm_connector *connector;
+       int entry = 0;
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list,
+                           head) {
+               struct psb_intel_output *psb_intel_output =
+                   to_psb_intel_output(connector);
+               if (type_mask & (1 << psb_intel_output->type))
+                       index_mask |= (1 << entry);
+               entry++;
+       }
+       return index_mask;
+}
+
+/* current intel driver doesn't take advantage of encoders
+   always give back the encoder for the connector
+*/
+struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector)
+{
+       struct psb_intel_output *psb_intel_output =
+                                       to_psb_intel_output(connector);
+
+       return &psb_intel_output->enc;
+}
+
+struct mrst_limit_t {
+       struct psb_intel_range_t dot, m, p1;
+};
+
+struct mrst_clock_t {
+       /* derived values */
+       int dot;
+       int m;
+       int p1;
+};
+
+#define COUNT_MAX 0x10000000
+
+static const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
+       .dpms = mdfld_crtc_dpms,
+       .mode_fixup = psb_intel_crtc_mode_fixup,
+       .mode_set = mdfld_crtc_mode_set,
+       .mode_set_base = mdfld__intel_pipe_set_base,
+       .prepare = psb_intel_crtc_prepare,
+       .commit = psb_intel_crtc_commit,
+};
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+#include "mdfld_dsi_dbi_dpu.h"
+#endif
+
+#include <linux/pm_runtime.h>
+
+void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
+{
+       int count, temp;
+       u32 pipeconf_reg = PIPEACONF;
+       
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               pipeconf_reg = PIPEBCONF;
+               break;
+       case 2:
+               pipeconf_reg = PIPECCONF;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return;
+       }
+
+       /* FIXME JLIU7_PO */
+       psb_intel_wait_for_vblank(dev);
+       return;
+
+       /* Wait for for the pipe disable to take effect. */
+       for (count = 0; count < COUNT_MAX; count++) {
+               temp = REG_READ(pipeconf_reg);
+               if ((temp & PIPEACONF_PIPE_STATE) == 0)
+                       break;
+       }
+
+       PSB_DEBUG_ENTRY("cout = %d. \n", count);
+}
+
+void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
+{
+       int count, temp;
+       u32 pipeconf_reg = PIPEACONF;
+       
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               pipeconf_reg = PIPEBCONF;
+               break;
+       case 2:
+               pipeconf_reg = PIPECCONF;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return;
+       }
+
+       /* FIXME JLIU7_PO */
+       psb_intel_wait_for_vblank(dev);
+       return;
+
+       /* Wait for for the pipe enable to take effect. */
+       for (count = 0; count < COUNT_MAX; count++) {
+               temp = REG_READ(pipeconf_reg);
+               if ((temp & PIPEACONF_PIPE_STATE) == 1)
+                       break;
+       }
+
+       PSB_DEBUG_ENTRY("cout = %d. \n", count);
+}
+
+
+static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc,
+                                struct drm_file *file_priv,
+                                uint32_t handle,
+                                uint32_t width, uint32_t height)
+{
+       struct drm_device *dev = crtc->dev;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
+       int pipe = psb_intel_crtc->pipe;
+       uint32_t control = CURACNTR;
+       uint32_t base = CURABASE;
+       uint32_t temp;
+       size_t addr = 0;
+       uint32_t page_offset;
+       size_t size;
+       void *bo;
+       int ret;
+
+       DRM_DEBUG("\n");
+
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               control = CURBCNTR;
+               base = CURBBASE;
+               break;
+       case 2:
+               control = CURCCNTR;
+               base = CURCBASE;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return -EINVAL;
+       }
+       
+#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+       if (pipe != 0)
+               return 0;
+#endif 
+       /* if we want to turn of the cursor ignore width and height */
+       if (!handle) {
+               DRM_DEBUG("cursor off\n");
+               /* turn off the cursor */
+               temp = 0;
+               temp |= CURSOR_MODE_DISABLE;
+
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                             OSPM_UHB_ONLY_IF_ON)) {
+                       REG_WRITE(control, temp);
+                       REG_WRITE(base, 0);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               }
+
+               /* unpin the old bo */
+               if (psb_intel_crtc->cursor_bo) {
+                       mode_dev->bo_unpin_for_scanout(dev,
+                                                      psb_intel_crtc->
+                                                      cursor_bo);
+                       psb_intel_crtc->cursor_bo = NULL;
+               }
+               return 0;
+       }
+
+       /* Currently we only support 64x64 cursors */
+       if (width != 64 || height != 64) {
+               DRM_ERROR("we currently only support 64x64 cursors\n");
+               return -EINVAL;
+       }
+
+       bo = mode_dev->bo_from_handle(dev, file_priv, handle);
+       if (!bo)
+               return -ENOENT;
+
+       ret = mode_dev->bo_pin_for_scanout(dev, bo);
+       if (ret)
+               return ret;
+       size = mode_dev->bo_size(dev, bo);
+       if (size < width * height * 4) {
+               DRM_ERROR("buffer is to small\n");
+               return -ENOMEM;
+       }
+
+        /*insert this bo into gtt*/
+//        DRM_INFO("%s: map meminfo for hw cursor. handle %x, pipe = %d \n", __FUNCTION__, handle, pipe);
+
+        ret = psb_gtt_map_meminfo(dev, (IMG_HANDLE)handle, &page_offset);
+        if(ret) {
+                DRM_ERROR("Can not map meminfo to GTT. handle 0x%x\n", handle);
+                return ret;
+        }
+
+       addr = page_offset << PAGE_SHIFT;
+
+       psb_intel_crtc->cursor_addr = addr;
+
+       temp = 0;
+       /* set the pipe for the cursor */
+       temp |= (pipe << 28);
+       temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               REG_WRITE(control, temp);
+               REG_WRITE(base, addr);
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+
+       /* unpin the old bo */
+       if (psb_intel_crtc->cursor_bo && psb_intel_crtc->cursor_bo != bo) {
+               mode_dev->bo_unpin_for_scanout(dev, psb_intel_crtc->cursor_bo);
+               psb_intel_crtc->cursor_bo = bo;
+       }
+
+       return 0;
+}
+
+static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+       struct drm_device *dev = crtc->dev;
+#ifndef CONFIG_MDFLD_DSI_DPU
+       struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+#else
+       struct psb_drm_dpu_rect rect;
+#endif
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       int pipe = psb_intel_crtc->pipe;
+       uint32_t pos = CURAPOS;
+       uint32_t base = CURABASE;
+       uint32_t temp = 0;
+       uint32_t addr;
+
+       switch (pipe) {
+       case 0:
+#ifndef CONFIG_MDFLD_DSI_DPU
+               if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
+                       mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_0);
+#else /*CONFIG_MDFLD_DSI_DPU*/
+               rect.x = x;
+               rect.y = y;
+               
+               mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect);
+               mdfld_dpu_exit_dsr(dev);
+#endif
+               break;
+       case 1:
+               pos = CURBPOS;
+               base = CURBBASE;
+               break;
+       case 2:
+#ifndef CONFIG_MDFLD_DSI_DPU
+               if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
+                       mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_2);
+#else /*CONFIG_MDFLD_DSI_DPU*/
+               mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
+               mdfld_dpu_exit_dsr(dev);
+#endif
+               pos = CURCPOS;
+               base = CURCBASE;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return -EINVAL;
+       }
+               
+#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+       if (pipe != 0)
+               return 0;
+#endif 
+       if (x < 0) {
+               temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+               x = -x;
+       }
+       if (y < 0) {
+               temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+               y = -y;
+       }
+
+       temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+       temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+       addr = psb_intel_crtc->cursor_addr;
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                     OSPM_UHB_ONLY_IF_ON)) {
+               REG_WRITE(pos, temp);
+               REG_WRITE(base, addr);
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+
+       return 0;
+}
+
+static const struct drm_crtc_funcs mdfld_intel_crtc_funcs = {
+       .save = psb_intel_crtc_save,
+       .restore = psb_intel_crtc_restore,
+       .cursor_set = mdfld_intel_crtc_cursor_set,
+       .cursor_move = mdfld_intel_crtc_cursor_move,
+       .gamma_set = psb_intel_crtc_gamma_set,
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = psb_intel_crtc_destroy,
+       .page_flip = psb_intel_crtc_page_flip,
+};
+
+static struct drm_device globle_dev;
+
+void mdfld__intel_plane_set_alpha(int enable)
+{
+       struct drm_device *dev = &globle_dev;
+       int dspcntr_reg = DSPACNTR;
+       u32 dspcntr;
+
+       dspcntr = REG_READ(dspcntr_reg);
+
+       if (enable) {
+               dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
+               dspcntr |= DISPPLANE_32BPP;
+       } else {
+               dspcntr &= ~DISPPLANE_32BPP;
+               dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+       }
+
+       REG_WRITE(dspcntr_reg, dspcntr);
+}
+
+static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
+                               struct drm_framebuffer *old_fb)
+{
+       struct drm_device *dev = crtc->dev;
+       /* struct drm_i915_master_private *master_priv; */
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+       struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
+       int pipe = psb_intel_crtc->pipe;
+       unsigned long Start, Offset;
+       int dsplinoff = DSPALINOFF;
+       int dspsurf = DSPASURF;
+       int dspstride = DSPASTRIDE;
+       int dspcntr_reg = DSPACNTR;
+       u32 dspcntr;
+       int ret = 0;
+
+       memcpy(&globle_dev, dev, sizeof(struct drm_device));
+
+       PSB_DEBUG_ENTRY("pipe = 0x%x. \n", pipe);
+
+       /* no fb bound */
+       if (!crtc->fb) {
+               PSB_DEBUG_ENTRY("No FB bound\n");
+               return 0;
+       }
+
+       switch (pipe) {
+       case 0:
+               dsplinoff = DSPALINOFF;
+               break;
+       case 1:
+               dsplinoff = DSPBLINOFF;
+               dspsurf = DSPBSURF;
+               dspstride = DSPBSTRIDE;
+               dspcntr_reg = DSPBCNTR;
+               break;
+       case 2:
+               dsplinoff = DSPCLINOFF;
+               dspsurf = DSPCSURF;
+               dspstride = DSPCSTRIDE;
+               dspcntr_reg = DSPCCNTR;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return -EINVAL;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                      OSPM_UHB_FORCE_POWER_ON))
+               return 0;
+
+       Start = mode_dev->bo_offset(dev, psbfb);
+       Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
+       REG_WRITE(dspstride, crtc->fb->pitch);
+       dspcntr = REG_READ(dspcntr_reg);
+       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+
+       switch (crtc->fb->bits_per_pixel) {
+       case 8:
+               dspcntr |= DISPPLANE_8BPP;
+               break;
+       case 16:
+               if (crtc->fb->depth == 15)
+                       dspcntr |= DISPPLANE_15_16BPP;
+               else
+                       dspcntr |= DISPPLANE_16BPP;
+               break;
+       case 24:
+       case 32:
+               dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+               break;
+       default:
+               DRM_ERROR("Unknown color depth\n");
+               ret = -EINVAL;
+               goto psb_intel_pipe_set_base_exit;
+       }
+       REG_WRITE(dspcntr_reg, dspcntr);
+
+       PSB_DEBUG_ENTRY("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+
+       REG_WRITE(dsplinoff, Offset);
+       REG_READ(dsplinoff);
+       REG_WRITE(dspsurf, Start);
+       REG_READ(dspsurf);
+
+psb_intel_pipe_set_base_exit:
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       return ret;
+}
+
+/**
+ * Disable the pipe, plane and pll.
+ *
+ */
+void mdfld_disable_crtc (struct drm_device *dev, int pipe)
+{
+       int dpll_reg = MRST_DPLL_A;
+       int dspcntr_reg = DSPACNTR;
+       int dspbase_reg = MRST_DSPABASE;
+       int pipeconf_reg = PIPEACONF;
+       u32 temp;
+
+       PSB_DEBUG_ENTRY("pipe = %d \n", pipe);
+
+
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               dpll_reg = MDFLD_DPLL_B;
+               dspcntr_reg = DSPBCNTR;
+               dspbase_reg = DSPBSURF;
+               pipeconf_reg = PIPEBCONF;
+               break;
+       case 2:
+               dpll_reg = MRST_DPLL_A;
+               dspcntr_reg = DSPCCNTR;
+               dspbase_reg = MDFLD_DSPCBASE;
+               pipeconf_reg = PIPECCONF;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return;
+       }
+
+       if (pipe != 1)
+               mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe), HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+       /* Disable display plane */
+       temp = REG_READ(dspcntr_reg);
+       if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+               REG_WRITE(dspcntr_reg,
+                         temp & ~DISPLAY_PLANE_ENABLE);
+               /* Flush the plane changes */
+               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+               REG_READ(dspbase_reg);
+       }
+
+       /* FIXME_JLIU7 MDFLD_PO revisit */
+       /* Wait for vblank for the disable to take effect */
+// MDFLD_PO_JLIU7              psb_intel_wait_for_vblank(dev);
+
+       /* Next, disable display pipes */
+       temp = REG_READ(pipeconf_reg);
+       if ((temp & PIPEACONF_ENABLE) != 0) {
+               temp &= ~PIPEACONF_ENABLE;
+               temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
+               REG_WRITE(pipeconf_reg, temp);
+               REG_READ(pipeconf_reg);
+
+               /* Wait for for the pipe disable to take effect. */
+               mdfldWaitForPipeDisable(dev, pipe);
+       }
+
+       temp = REG_READ(dpll_reg);
+       if (temp & DPLL_VCO_ENABLE) {
+               if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
+                               || (pipe == 1)){
+                       temp &= ~(DPLL_VCO_ENABLE);
+                       REG_WRITE(dpll_reg, temp);
+                       REG_READ(dpll_reg);
+                       /* Wait for the clocks to turn off. */
+                       /* FIXME_MDFLD PO may need more delay */
+                       udelay(500);
+
+                       if (!(temp & MDFLD_PWR_GATE_EN)) {
+                               /* gating power of DPLL */
+                               REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+                               /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                               udelay(5000);
+                       }
+               }
+       }
+
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+       struct drm_device *dev = crtc->dev;
+       DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       int pipe = psb_intel_crtc->pipe;
+       int dpll_reg = MRST_DPLL_A;
+       int dspcntr_reg = DSPACNTR;
+       int dspbase_reg = MRST_DSPABASE;
+       int pipeconf_reg = PIPEACONF;
+       u32 pipestat_reg = PIPEASTAT;
+       u32 pipeconf = dev_priv->pipeconf;
+       u32 dspcntr = dev_priv->dspcntr;
+       u32 temp;
+       bool enabled;
+       int timeout = 0;
+
+       PSB_DEBUG_ENTRY("mode = %d, pipe = %d \n", mode, pipe);
+
+       /* Ignore if system is already in DSR and in suspended state. */
+       if ((gbgfxsuspended) && (gbdispstatus == false) && (mode == DRM_MODE_DPMS_OFF)) {
+#if CONFIG_PM_RUNTIME
+               if ((dev_priv->rpm_enabled) && (pipe == 1)){
+                       // dev_priv->is_mipi_on = false;
+                       pm_request_idle(&gpDrmDevice->pdev->dev);
+               }
+#endif
+               return;
+       } else if (mode == DRM_MODE_DPMS_ON) {
+               //do not need to set gbdispstatus=true in crtc.
+               //this will be set in encoder's DPMS callback.
+               //gbdispstatus = true;
+       }
+
+/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
+/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
+
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               dpll_reg = DPLL_B;
+               dspcntr_reg = DSPBCNTR;
+               dspbase_reg = MRST_DSPBBASE;
+               pipeconf_reg = PIPEBCONF;
+               pipeconf = dev_priv->pipeconf1;
+               dspcntr = dev_priv->dspcntr1;
+               dpll_reg = MDFLD_DPLL_B;
+               break;
+       case 2:
+               dpll_reg = MRST_DPLL_A;
+               dspcntr_reg = DSPCCNTR;
+               dspbase_reg = MDFLD_DSPCBASE;
+               pipeconf_reg = PIPECCONF;
+               pipestat_reg = PIPECSTAT;
+               pipeconf = dev_priv->pipeconf2;
+               dspcntr = dev_priv->dspcntr2;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                      OSPM_UHB_FORCE_POWER_ON))
+               return;
+
+       /* XXX: When our outputs are all unaware of DPMS modes other than off
+        * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+        */
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+               /* Enable the DPLL */
+               temp = REG_READ(dpll_reg);
+
+               if ((temp & DPLL_VCO_ENABLE) == 0) {
+                       /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+                       if (temp & MDFLD_PWR_GATE_EN) {
+                               temp &= ~MDFLD_PWR_GATE_EN;
+                               REG_WRITE(dpll_reg, temp);
+                               /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                               udelay(500);
+                       }
+
+                       REG_WRITE(dpll_reg, temp);
+                       REG_READ(dpll_reg);
+                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                       udelay(500);
+                       
+                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+                       REG_READ(dpll_reg);
+
+                       /**
+                        * wait for DSI PLL to lock
+                        * NOTE: only need to poll status of pipe 0 and pipe 1,
+                        * since both MIPI pipes share the same PLL.
+                        */
+                       while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+                               udelay(150);
+                               timeout ++;
+                       }
+               }
+
+               /* Enable the plane */
+               temp = REG_READ(dspcntr_reg);
+               if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+                       REG_WRITE(dspcntr_reg,
+                               temp | DISPLAY_PLANE_ENABLE);
+                       /* Flush the plane changes */
+                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+               }
+
+               /* Enable the pipe */
+               temp = REG_READ(pipeconf_reg);
+               if ((temp & PIPEACONF_ENABLE) == 0) {
+                       REG_WRITE(pipeconf_reg, pipeconf);
+
+                       /* Wait for for the pipe enable to take effect. */
+                       mdfldWaitForPipeEnable(dev, pipe);
+               }
+
+               /*workaround for sighting 3741701 Random X blank display*/
+               /*perform w/a in video mode only on pipe A or C*/
+               if ((pipe == 0 || pipe == 2) &&
+                       (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DPI)) {
+                       REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
+                       msleep(100);
+                       if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) {
+                               printk(KERN_ALERT "OK");
+                       } else {
+                               printk(KERN_ALERT "STUCK!!!!");
+                               /*shutdown controller*/
+                               temp = REG_READ(dspcntr_reg);
+                               REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+                               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                               /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
+                               REG_WRITE(0xb048, 1);
+                               msleep(100);
+                               temp = REG_READ(pipeconf_reg);
+                               temp &= ~PIPEACONF_ENABLE;
+                               REG_WRITE(pipeconf_reg, temp);
+                               msleep(100); /*wait for pipe disable*/
+                       /*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
+                       printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/
+                               REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0);
+                               msleep(100);
+                       printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
+                       printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));
+                               REG_WRITE(0xb004, REG_READ(0xb004));
+                               /* try to bring the controller back up again*/
+                               REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 1);
+                               temp = REG_READ(dspcntr_reg);
+                               REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+                               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                               /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
+                               REG_WRITE(0xb048, 2);
+                               msleep(100);
+                               temp = REG_READ(pipeconf_reg);
+                               temp |= PIPEACONF_ENABLE;
+                               REG_WRITE(pipeconf_reg, temp);
+                       }
+               }
+
+               psb_intel_crtc_load_lut(crtc);
+
+               /* Give the overlay scaler a chance to enable
+                  if it's on this pipe */
+               /* psb_intel_crtc_dpms_video(crtc, true); TODO */
+
+               break;
+       case DRM_MODE_DPMS_OFF:
+               /* Give the overlay scaler a chance to disable
+                * if it's on this pipe */
+               /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
+               if (pipe != 1)
+                       mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe), HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+               /* Disable the VGA plane that we never use */
+               REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+               /* Disable display plane */
+               temp = REG_READ(dspcntr_reg);
+               if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+                       REG_WRITE(dspcntr_reg,
+                                 temp & ~DISPLAY_PLANE_ENABLE);
+                       /* Flush the plane changes */
+                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                       REG_READ(dspbase_reg);
+               }
+
+               /* FIXME_JLIU7 MDFLD_PO revisit */
+               /* Wait for vblank for the disable to take effect */
+// MDFLD_PO_JLIU7              psb_intel_wait_for_vblank(dev);
+
+               /* Next, disable display pipes */
+               temp = REG_READ(pipeconf_reg);
+               if ((temp & PIPEACONF_ENABLE) != 0) {
+                       temp &= ~PIPEACONF_ENABLE;
+                       temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
+                       REG_WRITE(pipeconf_reg, temp);
+//                     REG_WRITE(pipeconf_reg, 0);
+                       REG_READ(pipeconf_reg);
+
+                       /* Wait for for the pipe disable to take effect. */
+                       mdfldWaitForPipeDisable(dev, pipe);
+               }
+
+               temp = REG_READ(dpll_reg);
+               if (temp & DPLL_VCO_ENABLE) {
+                       if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
+                                       || (pipe == 1)){
+                               temp &= ~(DPLL_VCO_ENABLE);
+                               REG_WRITE(dpll_reg, temp);
+                               REG_READ(dpll_reg);
+                               /* Wait for the clocks to turn off. */
+                               /* FIXME_MDFLD PO may need more delay */
+                               udelay(500);
+#if 0 /* MDFLD_PO_JLIU7 */     
+               if (!(temp & MDFLD_PWR_GATE_EN)) {
+                       /* gating power of DPLL */
+                       REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                       udelay(5000);
+               }
+#endif  /* MDFLD_PO_JLIU7 */   
+                       }
+               }
+               break;
+       }
+
+       enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+
+#if 0                          /* JB: Add vblank support later */
+       if (enabled)
+               dev_priv->vblank_pipe |= (1 << pipe);
+       else
+               dev_priv->vblank_pipe &= ~(1 << pipe);
+#endif
+
+#if 0                          /* JB: Add sarea support later */
+       if (!dev->primary->master)
+               return;
+
+       master_priv = dev->primary->master->driver_priv;
+       if (!master_priv->sarea_priv)
+               return;
+
+       switch (pipe) {
+       case 0:
+               master_priv->sarea_priv->planeA_w =
+                   enabled ? crtc->mode.hdisplay : 0;
+               master_priv->sarea_priv->planeA_h =
+                   enabled ? crtc->mode.vdisplay : 0;
+               break;
+       case 1:
+               master_priv->sarea_priv->planeB_w =
+                   enabled ? crtc->mode.hdisplay : 0;
+               master_priv->sarea_priv->planeB_h =
+                   enabled ? crtc->mode.vdisplay : 0;
+               break;
+       default:
+               DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
+               break;
+       }
+#endif
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+
+#define MDFLD_LIMT_DPLL_19         0
+#define MDFLD_LIMT_DPLL_25         1
+#define MDFLD_LIMT_DPLL_83         2
+#define MDFLD_LIMT_DPLL_100        3
+#define MDFLD_LIMT_DSIPLL_19       4
+#define MDFLD_LIMT_DSIPLL_25       5
+#define MDFLD_LIMT_DSIPLL_83       6
+#define MDFLD_LIMT_DSIPLL_100      7
+
+#define MDFLD_DOT_MIN            19750  /* FIXME_MDFLD JLIU7 need to find out  min & max for MDFLD */
+#define MDFLD_DOT_MAX            120000
+#define MDFLD_DPLL_M_MIN_19        113
+#define MDFLD_DPLL_M_MAX_19        155
+#define MDFLD_DPLL_P1_MIN_19       2
+#define MDFLD_DPLL_P1_MAX_19       10
+#define MDFLD_DPLL_M_MIN_25        101
+#define MDFLD_DPLL_M_MAX_25        130
+#define MDFLD_DPLL_P1_MIN_25       2
+#define MDFLD_DPLL_P1_MAX_25       10
+#define MDFLD_DPLL_M_MIN_83        64
+#define MDFLD_DPLL_M_MAX_83        64
+#define MDFLD_DPLL_P1_MIN_83       2
+#define MDFLD_DPLL_P1_MAX_83       2
+#define MDFLD_DPLL_M_MIN_100       64
+#define MDFLD_DPLL_M_MAX_100       64
+#define MDFLD_DPLL_P1_MIN_100      2
+#define MDFLD_DPLL_P1_MAX_100      2
+#define MDFLD_DSIPLL_M_MIN_19      131
+#define MDFLD_DSIPLL_M_MAX_19      175
+#define MDFLD_DSIPLL_P1_MIN_19     3
+#define MDFLD_DSIPLL_P1_MAX_19     8
+#define MDFLD_DSIPLL_M_MIN_25      97
+#define MDFLD_DSIPLL_M_MAX_25      140
+#define MDFLD_DSIPLL_P1_MIN_25     3
+#define MDFLD_DSIPLL_P1_MAX_25     9
+#define MDFLD_DSIPLL_M_MIN_83      33
+#define MDFLD_DSIPLL_M_MAX_83      92
+#define MDFLD_DSIPLL_P1_MIN_83     2
+#define MDFLD_DSIPLL_P1_MAX_83     3
+#define MDFLD_DSIPLL_M_MIN_100     97
+#define MDFLD_DSIPLL_M_MAX_100     140
+#define MDFLD_DSIPLL_P1_MIN_100            3
+#define MDFLD_DSIPLL_P1_MAX_100            9
+
+static const struct mrst_limit_t mdfld_limits[] = {
+       {                       /* MDFLD_LIMT_DPLL_19 */
+        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+        .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
+        .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
+        },
+       {                       /* MDFLD_LIMT_DPLL_25 */
+        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+        .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
+        .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
+        },
+       {                       /* MDFLD_LIMT_DPLL_83 */
+        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+        .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
+        .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
+        },
+       {                       /* MDFLD_LIMT_DPLL_100 */
+        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+        .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
+        .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
+        },
+       {                       /* MDFLD_LIMT_DSIPLL_19 */
+        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+        .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
+        .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
+        },
+       {                       /* MDFLD_LIMT_DSIPLL_25 */
+        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+        .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
+        .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
+        },
+       {                       /* MDFLD_LIMT_DSIPLL_83 */
+        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+        .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
+        .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
+        },
+       {                       /* MDFLD_LIMT_DSIPLL_100 */
+        .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+        .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
+        .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
+        },
+};
+
+#define MDFLD_M_MIN        21
+#define MDFLD_M_MAX        180
+static const u32 mdfld_m_converts[] = {
+/* M configuration table from 9-bit LFSR table */
+       224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
+       173, 342, 171, 85, 298, 149, 74, 37, 18, 265,   /* 31 - 40 */
+       388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
+       83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
+       341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
+       461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
+       106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
+       71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
+       253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
+       478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
+       477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
+       210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
+       145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
+       380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
+       103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
+       396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
+};
+
+static const struct mrst_limit_t *mdfld_limit(struct drm_crtc *crtc)
+{
+       const struct mrst_limit_t *limit = NULL;
+       struct drm_device *dev = crtc->dev;
+       DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+
+       if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
+           || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
+               if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19))
+                       limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
+               else if (dev_priv->ksel == KSEL_BYPASS_25) 
+                       limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
+               else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
+                       limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
+               else if ((dev_priv->ksel == KSEL_BYPASS_83_100) &&
+                        (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
+                       limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
+       } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
+               if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19))
+                       limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
+               else if (dev_priv->ksel == KSEL_BYPASS_25) 
+                       limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
+               else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
+                       limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
+               else if ((dev_priv->ksel == KSEL_BYPASS_83_100) &&
+                        (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
+                       limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
+       } else {
+               limit = NULL;
+               PSB_DEBUG_ENTRY("mdfld_limit Wrong display type. \n");
+       }
+
+       return limit;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+static void mdfld_clock(int refclk, struct mrst_clock_t *clock)
+{
+       clock->dot = (refclk * clock->m) / clock->p1;
+}
+
+/**
+ * Returns a set of divisors for the desired target clock with the given refclk,
+ * or FALSE.  Divisor values are the actual divisors for
+ */
+static bool
+mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
+               struct mrst_clock_t *best_clock)
+{
+       struct mrst_clock_t clock;
+       const struct mrst_limit_t *limit = mdfld_limit(crtc);
+       int err = target;
+
+       memset(best_clock, 0, sizeof(*best_clock));
+
+       PSB_DEBUG_ENTRY("mdfldFindBestPLL target = %d,"
+                        "m_min = %d, m_max = %d, p_min = %d, p_max = %d. \n", target, limit->m.min, limit->m.max, limit->p1.min, limit->p1.max);
+
+       for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
+               for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
+                    clock.p1++) {
+                       int this_err;
+
+                       mdfld_clock(refclk, &clock);
+
+                       this_err = abs(clock.dot - target);
+                       if (this_err < err) {
+                               *best_clock = clock;
+                               err = this_err;
+                       }
+               }
+       }
+       PSB_DEBUG_ENTRY("mdfldFindBestPLL target = %d,"
+                        "m = %d, p = %d. \n", target, best_clock->m, best_clock->p1);
+       PSB_DEBUG_ENTRY("mdfldFindBestPLL err = %d.\n", err);
+       
+       return err != target;
+}
+
+static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
+                             struct drm_display_mode *mode,
+                             struct drm_display_mode *adjusted_mode,
+                             int x, int y,
+                             struct drm_framebuffer *old_fb)
+{
+       struct drm_device *dev = crtc->dev;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+       int pipe = psb_intel_crtc->pipe;
+       int fp_reg = MRST_FPA0;
+       int dpll_reg = MRST_DPLL_A;
+       int dspcntr_reg = DSPACNTR;
+       int pipeconf_reg = PIPEACONF;
+       int htot_reg = HTOTAL_A;
+       int hblank_reg = HBLANK_A;
+       int hsync_reg = HSYNC_A;
+       int vtot_reg = VTOTAL_A;
+       int vblank_reg = VBLANK_A;
+       int vsync_reg = VSYNC_A;
+       int dspsize_reg = DSPASIZE; 
+       int dsppos_reg = DSPAPOS; 
+       int pipesrc_reg = PIPEASRC;
+       u32 *pipeconf = &dev_priv->pipeconf;
+       u32 *dspcntr = &dev_priv->dspcntr;
+       int refclk = 0;
+       int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0;
+       struct mrst_clock_t clock;
+       bool ok;
+       u32 dpll = 0, fp = 0;
+       bool is_crt = false, is_lvds = false, is_tv = false;
+       bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct psb_intel_output *psb_intel_output = NULL;
+       uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
+       struct drm_encoder *encoder;
+       struct drm_connector * connector;
+       int timeout = 0;
+
+       PSB_DEBUG_ENTRY("pipe = 0x%x \n", pipe);
+
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               fp_reg = FPB0;
+               dpll_reg = DPLL_B;
+               dspcntr_reg = DSPBCNTR;
+               pipeconf_reg = PIPEBCONF;
+               htot_reg = HTOTAL_B;
+               hblank_reg = HBLANK_B;
+               hsync_reg = HSYNC_B;
+               vtot_reg = VTOTAL_B;
+               vblank_reg = VBLANK_B;
+               vsync_reg = VSYNC_B;
+               dspsize_reg = DSPBSIZE; 
+               dsppos_reg = DSPBPOS; 
+               pipesrc_reg = PIPEBSRC;
+               pipeconf = &dev_priv->pipeconf1;
+               dspcntr = &dev_priv->dspcntr1;
+               fp_reg = MDFLD_DPLL_DIV0;
+               dpll_reg = MDFLD_DPLL_B;
+               break;
+       case 2:
+               dpll_reg = MRST_DPLL_A;
+               dspcntr_reg = DSPCCNTR;
+               pipeconf_reg = PIPECCONF;
+               htot_reg = HTOTAL_C;
+               hblank_reg = HBLANK_C;
+               hsync_reg = HSYNC_C;
+               vtot_reg = VTOTAL_C;
+               vblank_reg = VBLANK_C;
+               vsync_reg = VSYNC_C;
+               dspsize_reg = DSPCSIZE; 
+               dsppos_reg = DSPCPOS; 
+               pipesrc_reg = PIPECSRC;
+               pipeconf = &dev_priv->pipeconf2;
+               dspcntr = &dev_priv->dspcntr2;
+               break;
+       default:
+               DRM_ERROR("Illegal Pipe Number. \n");
+               return 0;
+       }
+
+       PSB_DEBUG_ENTRY("adjusted_hdisplay = %d\n",
+                adjusted_mode->hdisplay);
+       PSB_DEBUG_ENTRY("adjusted_vdisplay = %d\n",
+                adjusted_mode->vdisplay);
+       PSB_DEBUG_ENTRY("adjusted_hsync_start = %d\n",
+                adjusted_mode->hsync_start);
+       PSB_DEBUG_ENTRY("adjusted_hsync_end = %d\n",
+                adjusted_mode->hsync_end);
+       PSB_DEBUG_ENTRY("adjusted_htotal = %d\n",
+                adjusted_mode->htotal);
+       PSB_DEBUG_ENTRY("adjusted_vsync_start = %d\n",
+                adjusted_mode->vsync_start);
+       PSB_DEBUG_ENTRY("adjusted_vsync_end = %d\n",
+                adjusted_mode->vsync_end);
+       PSB_DEBUG_ENTRY("adjusted_vtotal = %d\n",
+                adjusted_mode->vtotal);
+       PSB_DEBUG_ENTRY("adjusted_clock = %d\n",
+                adjusted_mode->clock);
+       PSB_DEBUG_ENTRY("hdisplay = %d\n",
+                mode->hdisplay);
+       PSB_DEBUG_ENTRY("vdisplay = %d\n",
+                mode->vdisplay);
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON))
+               return 0;
+
+       memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode));
+       memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode));
+
+       list_for_each_entry(connector, &mode_config->connector_list, head) {
+               if(!connector)
+                       continue;
+                       
+               encoder = connector->encoder;
+               
+               if(!encoder)
+                       continue;
+
+               if (encoder->crtc != crtc)
+                       continue;
+
+               psb_intel_output = to_psb_intel_output(connector);
+               
+               PSB_DEBUG_ENTRY("output->type = 0x%x \n", psb_intel_output->type);
+
+               switch (psb_intel_output->type) {
+               case INTEL_OUTPUT_LVDS:
+                       is_lvds = true;
+                       break;
+               case INTEL_OUTPUT_TVOUT:
+                       is_tv = true;
+                       break;
+               case INTEL_OUTPUT_ANALOG:
+                       is_crt = true;
+                       break;
+               case INTEL_OUTPUT_MIPI:
+                       is_mipi = true;
+                       break;
+               case INTEL_OUTPUT_MIPI2:
+                       is_mipi2 = true;
+                       break;
+               case INTEL_OUTPUT_HDMI:
+                       is_hdmi = true;
+                       break;
+               }
+       }
+
+       /* Disable the VGA plane that we never use */
+       REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+       /* Disable the panel fitter if it was on our pipe */
+       if (psb_intel_panel_fitter_pipe(dev) == pipe)
+               REG_WRITE(PFIT_CONTROL, 0);
+
+       /* pipesrc and dspsize control the size that is scaled from,
+        * which should always be the user's requested size.
+        */
+       if (pipe == 1) {
+               /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite 
+                * width/height and souce image size registers with the adjusted mode for pipe B. */
+
+               /* The defined sprite rectangle must always be completely contained within the displayable 
+                * area of the screen image (frame buffer). */
+               REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16) 
+                               | (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
+               /* Set the CRTC with encoder mode. */
+               REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
+                                | (mode->crtc_vdisplay - 1));
+       } else {
+               REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1));
+               REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
+       }
+
+       REG_WRITE(dsppos_reg, 0);
+
+       if (psb_intel_output)
+               drm_connector_property_get_value(&psb_intel_output->base,
+                       dev->mode_config.scaling_mode_property, &scalingType);
+
+       if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
+               /*Moorestown doesn't have register support for centering so we need to
+                 mess with the h/vblank and h/vsync start and ends to get centering*/
+               int offsetX = 0, offsetY = 0;
+
+               offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+               offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
+
+               REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
+                       ((adjusted_mode->crtc_htotal - 1) << 16));
+               REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
+                       ((adjusted_mode->crtc_vtotal - 1) << 16));
+               REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) |
+                       ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
+               REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) |
+                       ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
+               REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) |
+                       ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
+               REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) |
+                       ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
+       } else {
+               REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+                       ((adjusted_mode->crtc_htotal - 1) << 16));
+               REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+                       ((adjusted_mode->crtc_vtotal - 1) << 16));
+               REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+                       ((adjusted_mode->crtc_hblank_end - 1) << 16));
+               REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+                       ((adjusted_mode->crtc_hsync_end - 1) << 16));
+               REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+                       ((adjusted_mode->crtc_vblank_end - 1) << 16));
+               REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+                       ((adjusted_mode->crtc_vsync_end - 1) << 16));
+       }
+
+       /* Flush the plane changes */
+       {
+               struct drm_crtc_helper_funcs *crtc_funcs =
+                   crtc->helper_private;
+               crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+       }
+
+       /* setup pipeconf */
+       *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
+
+       /* Set up the display plane register */
+       *dspcntr = REG_READ(dspcntr_reg);
+       *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
+       *dspcntr |= DISPLAY_PLANE_ENABLE;
+/* MDFLD_PO_JLIU7      dspcntr |= DISPPLANE_BOTTOM; */
+/* MDFLD_PO_JLIU7      dspcntr |= DISPPLANE_GAMMA_ENABLE; */
+
+       if (is_mipi2)
+       {
+               goto mrst_crtc_mode_set_exit;
+       }
+/* FIXME JLIU7 Add MDFLD HDMI supports */
+/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */
+/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */
+       clk = adjusted_mode->clock;
+
+       if (is_hdmi) {
+               if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19))
+               {
+                       refclk = 19200;
+
+                       if (is_mipi || is_mipi2)
+                       {
+                               clk_n = 1, clk_p2 = 8;
+                       } else if (is_hdmi) {
+                               clk_n = 1, clk_p2 = 10;
+                       }
+               } else if (dev_priv->ksel == KSEL_BYPASS_25) { 
+                       refclk = 25000;
+
+                       if (is_mipi || is_mipi2)
+                       {
+                               clk_n = 1, clk_p2 = 8;
+                       } else if (is_hdmi) {
+                               clk_n = 1, clk_p2 = 10;
+                       }
+               } else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) {
+                       refclk = 83000;
+
+                       if (is_mipi || is_mipi2)
+                       {
+                               clk_n = 4, clk_p2 = 8;
+                       } else if (is_hdmi) {
+                               clk_n = 4, clk_p2 = 10;
+                       }
+               } else if ((dev_priv->ksel == KSEL_BYPASS_83_100) &&
+                          (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) {
+                       refclk = 100000;
+                       if (is_mipi || is_mipi2)
+                       {
+                               clk_n = 4, clk_p2 = 8;
+                       } else if (is_hdmi) {
+                               clk_n = 4, clk_p2 = 10;
+                       }
+               }
+
+               if (is_mipi)
+                       clk_byte = dev_priv->bpp / 8;
+               else if (is_mipi2)
+                       clk_byte = dev_priv->bpp2 / 8;
+       
+               clk_tmp = clk * clk_n * clk_p2 * clk_byte;
+
+               PSB_DEBUG_ENTRY("clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2);
+               PSB_DEBUG_ENTRY("adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp);
+
+               ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
+               dev_priv->tmds_clock_khz = clock.dot / (clk_n * clk_p2 * clk_byte);
+
+               if (!ok) {
+#if 0                          /* FIXME JLIU7 */
+                       DRM_ERROR("Couldn't find PLL settings for mode!\n");
+                       return;
+#endif                         /* FIXME JLIU7 */
+                       DRM_ERROR
+                           ("mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n");
+               } else {
+                       m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
+
+                       PSB_DEBUG_ENTRY("dot clock = %d,"
+                                "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m,
+                                clock.p1, m_conv);
+               }
+
+               dpll = REG_READ(dpll_reg);
+
+               if (dpll & DPLL_VCO_ENABLE) {
+                       dpll &= ~DPLL_VCO_ENABLE;
+                       REG_WRITE(dpll_reg, dpll);
+                       REG_READ(dpll_reg);
+
+                       /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
+                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                       udelay(500);
+
+                       /* reset M1, N1 & P1 */
+                       REG_WRITE(fp_reg, 0);
+                       dpll &= ~MDFLD_P1_MASK;
+                       REG_WRITE(dpll_reg, dpll);
+                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                       udelay(500);
+               }
+
+               /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+               if (dpll & MDFLD_PWR_GATE_EN) {
+                       dpll &= ~MDFLD_PWR_GATE_EN;
+                       REG_WRITE(dpll_reg, dpll);
+                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                       udelay(500);
+               }       
+
+               dpll = 0; 
+
+#if 0 /* FIXME revisit later */
+               if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19) || (dev_priv->ksel == KSEL_BYPASS_25)) {
+                       dpll &= ~MDFLD_INPUT_REF_SEL;   
+               } else if (dev_priv->ksel == KSEL_BYPASS_83_100) { 
+                       dpll |= MDFLD_INPUT_REF_SEL;    
+               }
+#endif /* FIXME revisit later */
+
+               if (is_hdmi)
+                       dpll |= MDFLD_VCO_SEL;  
+
+               fp = (clk_n / 2) << 16;
+               fp |= m_conv; 
+
+               /* compute bitmask from p1 value */
+               dpll |= (1 << (clock.p1 - 2)) << 17;
+
+#if 0 /* 1080p30 & 720p */
+               dpll = 0x00050000;
+               fp = 0x000001be;
+#endif 
+#if 0 /* 480p */
+               dpll = 0x02010000;
+               fp = 0x000000d2;
+#endif 
+       } else {
+#if 0 /*DBI_TPO_480x864*/
+               dpll = 0x00020000;
+               fp = 0x00000156; 
+#endif /* DBI_TPO_480x864 */ /* get from spec. */
+
+               dpll = 0x00800000;
+               fp = 0x000000c1;
+}
+
+       REG_WRITE(fp_reg, fp);
+       REG_WRITE(dpll_reg, dpll);
+       /* FIXME_MDFLD PO - change 500 to 1 after PO */
+       udelay(500);
+
+       dpll |= DPLL_VCO_ENABLE;
+       REG_WRITE(dpll_reg, dpll);
+       REG_READ(dpll_reg);
+
+       /* wait for DSI PLL to lock */
+       while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+               udelay(150);
+               timeout ++;
+       }
+
+       if (is_mipi)
+               goto mrst_crtc_mode_set_exit;
+
+       PSB_DEBUG_ENTRY("is_mipi = 0x%x \n", is_mipi);
+
+       REG_WRITE(pipeconf_reg, *pipeconf);
+       REG_READ(pipeconf_reg);
+
+       /* Wait for for the pipe enable to take effect. */
+//FIXME_JLIU7 HDMI     mrstWaitForPipeEnable(dev);
+
+       REG_WRITE(dspcntr_reg, *dspcntr);
+       psb_intel_wait_for_vblank(dev);
+
+mrst_crtc_mode_set_exit:
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       return 0;
+}
diff --git a/drivers/staging/mrst/drv/psb_intel_display.h b/drivers/staging/mrst/drv/psb_intel_display.h
new file mode 100644 (file)
index 0000000..a0b0283
--- /dev/null
@@ -0,0 +1,28 @@
+/* copyright (c) 2008, Intel Corporation
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ */
+
+#ifndef _INTEL_DISPLAY_H_
+#define _INTEL_DISPLAY_H_
+
+#include <drm/drmP.h>
+
+bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
+void mdfld__intel_plane_set_alpha(int enable);
+
+#endif
diff --git a/drivers/staging/mrst/drv/psb_intel_drv.h b/drivers/staging/mrst/drv/psb_intel_drv.h
new file mode 100644 (file)
index 0000000..8e0568a
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __INTEL_DRV_H__
+#define __INTEL_DRV_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <linux/gpio.h>
+
+#if 0 /* Debug HDMI */
+#include "psb_intel_hdmi_i2c.h"
+#endif 
+
+/* Temp Switch */
+#define MDFLD_HDMI_JLIU7_DEBUG_1 1 /* Debug HDMI - Can't enalbe HDMI */
+#define MDFLD_HDMI_JLIU7_1080 0 /* enable & remove it after switching to IAFW v.0.28. */
+/* Must be 0 but need to be revisited afte MDFLD PO */
+#define MDFLD_GCT_JLIU7 0
+
+/* Switch - don't change before PO */
+#define MDFLD_GET_SYNC_BURST 0 /* Consider BURST_MODE when calcaulation H/V sync counts */
+/* MDFLD FEATURE SWITCHES*/    
+/* MDFLD MIPI panels only one of them can be set to 1 */
+
+/* MDFLD KSEL only one of them can be set to 1 */ 
+#define KSEL_CRYSTAL_19_ENABLED 1
+#define KSEL_BYPASS_19_ENABLED 0
+#define KSEL_BYPASS_25_ENABLED 0
+#define KSEL_BYPASS_83_100_ENABLE 0
+
+#define KSEL_CRYSTAL_19 1
+#define KSEL_BYPASS_19 5
+#define KSEL_BYPASS_25 6
+#define KSEL_BYPASS_83_100 7
+/*
+ * MOORESTOWN defines
+ */
+#define DELAY_TIME1 2000 /* 1000 = 1ms */
+
+/*
+ * Display related stuff
+ */
+
+/* store information about an Ixxx DVO */
+/* The i830->i865 use multiple DVOs with multiple i2cs */
+/* the i915, i945 have a single sDVO i2c bus - which is different */
+#define MAX_OUTPUTS 6
+/* maximum connectors per crtcs in the mode set */
+#define INTELFB_CONN_LIMIT 4
+
+#define INTEL_I2C_BUS_DVO 1
+#define INTEL_I2C_BUS_SDVO 2
+
+/* these are outputs from the chip - integrated only
+ * external chips are via DVO or SDVO output */
+#define INTEL_OUTPUT_UNUSED 0
+#define INTEL_OUTPUT_ANALOG 1
+#define INTEL_OUTPUT_DVO 2
+#define INTEL_OUTPUT_SDVO 3
+#define INTEL_OUTPUT_LVDS 4
+#define INTEL_OUTPUT_TVOUT 5
+#define INTEL_OUTPUT_HDMI 6
+#define INTEL_OUTPUT_MIPI 7
+#define INTEL_OUTPUT_MIPI2 8
+
+#define INTEL_DVO_CHIP_NONE 0
+#define INTEL_DVO_CHIP_LVDS 1
+#define INTEL_DVO_CHIP_TMDS 2
+#define INTEL_DVO_CHIP_TVOUT 4
+
+enum mipi_panel_type {
+       NSC_800X480 = 1,
+       LGE_480X1024 = 2,
+       TPO_864X480 = 3
+};
+
+/**
+ * Hold information useally put on the device driver privates here,
+ * since it needs to be shared across multiple of devices drivers privates.
+*/
+struct psb_intel_mode_device {
+
+       /*
+        * Abstracted memory manager operations
+        */
+       void *(*bo_from_handle) (struct drm_device *dev,
+                                struct drm_file *file_priv,
+                                unsigned int handle);
+        size_t(*bo_size) (struct drm_device *dev, void *bo);
+        size_t(*bo_offset) (struct drm_device *dev, void *bo);
+       int (*bo_pin_for_scanout) (struct drm_device *dev, void *bo);
+       int (*bo_unpin_for_scanout) (struct drm_device *dev, void *bo);
+
+       /*
+        * Cursor
+        */
+       int cursor_needs_physical;
+
+       /*
+        * LVDS info
+        */
+       int backlight_duty_cycle;       /* restore backlight to this value */
+       bool panel_wants_dither;
+       struct drm_display_mode *panel_fixed_mode;
+       struct drm_display_mode *panel_fixed_mode2;
+       struct drm_display_mode *vbt_mode;      /* if any */
+
+       uint32_t saveBLC_PWM_CTL;
+};
+
+struct psb_intel_i2c_chan {
+       /* for getting at dev. private (mmio etc.) */
+       struct drm_device *drm_dev;
+       u32 reg;                /* GPIO reg */
+       struct i2c_adapter adapter;
+       struct i2c_algo_bit_data algo;
+       u8 slave_addr;
+};
+
+struct psb_intel_output {
+       struct drm_connector base;
+
+       struct drm_encoder enc;
+       int type;
+#if 1 /*MDFLD_HDMI_JLIU7*/
+       struct i2c_adapter *hdmi_i2c_adapter;   /* for control functions */
+#endif
+       struct psb_intel_i2c_chan *i2c_bus;     /* for control functions */
+       bool load_detect_temp;
+       void *dev_priv;
+
+       struct psb_intel_mode_device *mode_dev;
+
+};
+
+struct psb_intel_crtc_state {
+       uint32_t saveDSPCNTR;
+       uint32_t savePIPECONF;
+       uint32_t savePIPESRC;
+       uint32_t saveDPLL;
+       uint32_t saveFP0;
+       uint32_t saveFP1;
+       uint32_t saveHTOTAL;
+       uint32_t saveHBLANK;
+       uint32_t saveHSYNC;
+       uint32_t saveVTOTAL;
+       uint32_t saveVBLANK;
+       uint32_t saveVSYNC;
+       uint32_t saveDSPSTRIDE;
+       uint32_t saveDSPSIZE;
+       uint32_t saveDSPPOS;
+       uint32_t saveDSPBASE;
+       uint32_t savePalette[256];
+};
+
+struct psb_intel_crtc {
+       struct drm_crtc base;
+       int pipe;
+       int plane;
+       uint32_t cursor_addr;
+       u8 lut_r[256], lut_g[256], lut_b[256];
+       u8 lut_adj[256];
+       struct psb_intel_framebuffer *fbdev_fb;
+       /* a mode_set for fbdev users on this crtc */
+       struct drm_mode_set mode_set;
+
+       /* current bo we scanout from */
+       void *scanout_bo;
+
+       /* current bo we cursor from */
+       void *cursor_bo;
+
+       struct drm_display_mode saved_mode;
+       struct drm_display_mode saved_adjusted_mode;
+
+       struct psb_intel_mode_device *mode_dev;
+
+       /*crtc mode setting flags*/
+       u32 mode_flags;
+
+       /* Saved Crtc HW states */
+       struct psb_intel_crtc_state *crtc_state;
+       void *pending_flip;
+};
+
+#define to_psb_intel_crtc(x)   \
+               container_of(x, struct psb_intel_crtc, base)
+#define to_psb_intel_output(x) \
+               container_of(x, struct psb_intel_output, base)
+#define enc_to_psb_intel_output(x)     \
+               container_of(x, struct psb_intel_output, enc)
+#define to_psb_intel_framebuffer(x)    \
+               container_of(x, struct psb_intel_framebuffer, base)
+
+extern void psb_intel_crtc_init(struct drm_device *dev, int pipe,
+                           struct psb_intel_mode_device *mode_dev);
+extern void psb_intel_crt_init(struct drm_device *dev);
+extern void psb_intel_dvo_init(struct drm_device *dev);
+extern void psb_intel_tv_init(struct drm_device *dev);
+extern void mid_dsi_init(struct drm_device *dev,
+                   struct psb_intel_mode_device *mode_dev, int dsi_num);
+extern void mdfld_hdmi_init(struct drm_device *dev,
+                          struct psb_intel_mode_device *mode_dev);
+extern void mdfld_wld_init(struct drm_device *dev);
+
+extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc);
+extern void psb_intel_encoder_prepare(struct drm_encoder *encoder);
+extern void psb_intel_encoder_commit(struct drm_encoder *encoder);
+
+extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector
+                                             *connector);
+
+extern void psb_intel_wait_for_vblank(struct drm_device *dev);
+extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
+                                            int sdvoB);
+extern int intelfb_probe(struct drm_device *dev);
+extern int intelfb_remove(struct drm_device *dev,
+                         struct drm_framebuffer *fb);
+extern void mdfld_disable_crtc (struct drm_device *dev, int pipe);
+
+extern void mdfld_dbi_update_fb (struct drm_device *dev, int pipe);
+extern void mdfld_dbi_enter_dsr (struct drm_device *dev);
+extern void mdfld_dbi_exit_dsr (struct drm_device *dev, u32 update_src);
+extern void mdfld_dbi_update_panel (struct drm_device *dev, int pipe);
+extern void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level);
+extern void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat);
+extern void mdfld_dsi_dbi_CB_ready (struct drm_device *dev, u32 mipi_command_address_reg, u32 gen_fifo_stat_reg);
+extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
+extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
+
+#endif                         /* __INTEL_DRV_H__ */
diff --git a/drivers/staging/mrst/drv/psb_intel_hdmi.c b/drivers/staging/mrst/drv/psb_intel_hdmi.c
new file mode 100644 (file)
index 0000000..f7558a9
--- /dev/null
@@ -0,0 +1,1123 @@
+/*
+ * Copyright Â© 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     jim liu <jim.liu@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+#include "psb_intel_drv.h"
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_hdmi_reg.h"
+#include "psb_intel_hdmi_edid.h"
+#include "psb_intel_hdmi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_hdmi_audio_if.h"
+#include "mdfld_msic.h"
+#include "mdfld_hdcp_if.h"
+#include <linux/pm_runtime.h>
+#include <asm/intel_scu_ipc.h>
+
+/* FIXME_MDFLD HDMI EDID supports */
+
+static char EDID_Samsung[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] =
+{
+       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x4C, 0x2D, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 
+       0x14, 0x11, 0x01, 0x03, 0x80, 0x10, 0x09, 0x8C, 0x0A, 0xE2, 0xBD, 0xA1, 0x5B, 0x4A, 0x98, 0x24, 
+       0x15, 0x47, 0x4A, 0x20, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, 0x6E, 0x28, 
+       0x55, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x1E, 0x01, 0x1D, 0x00, 0xBC, 0x52, 0xD0, 0x1E, 0x20,
+       0xB8, 0x28, 0x55, 0x40, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x31, 
+       0x3D, 0x0F, 0x2E, 0x08, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC, 
+       0x00, 0x53, 0x41, 0x4D, 0x53, 0x55, 0x4E, 0x47, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xB3,
+       0x02, 0x03, 0x1A, 0x71, 0x46, 0x84, 0x13, 0x05, 0x14, 0x03, 0x12, 0x23, 0x09, 0x07, 0x07, 0x83, 
+       0x01, 0x00, 0x00, 0x66, 0x03, 0x0C, 0x00, 0x10, 0x00, 0x80, 0x01, 0x1D, 0x80, 0x18, 0x71, 0x1C, 
+       0x16, 0x20, 0x58, 0x2C, 0x25, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x9E, 0x01, 0x1D, 0x80, 0xD0, 
+       0x72, 0x1C, 0x16, 0x20, 0x10, 0x2C, 0x25, 0x80, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x9E, 0x8C, 0x0A, 
+       0xD0, 0x8A, 0x20, 0xE0, 0x2D, 0x10, 0x10, 0x3E, 0x96, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x18,
+       0x8C, 0x0A, 0xD0, 0x90, 0x20, 0x40, 0x31, 0x20, 0x0C, 0x40, 0x55, 0x00, 0xA0, 0x5A, 0x00, 0x00, 
+       0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0
+};
+
+static char EDID_Samsung_2493HM[EDID_LENGTH] =
+{
+       0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x68, 0x03, 0x34, 0x32, 0x49, 0x4b,
+       0x0c, 0x12, 0x01, 0x03, 0x0e, 0x34, 0x20, 0xa0, 0x2a, 0xef, 0x91, 0xa3, 0x54, 0x4c, 0x9b, 0x26,
+       0x0f, 0x50, 0x54, 0xbf, 0xef, 0x80, 0xa9, 0x40, 0x81, 0x80, 0x81, 0x40, 0x71, 0x4f, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, 0x23, 0x40, 0x30, 0x20,
+       0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4b, 0x1e,
+       0x51, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x53,
+       0x79, 0x6e, 0x63, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x00, 0x00, 0x00, 0xff,
+       0x00, 0x48, 0x56, 0x52, 0x51, 0x33, 0x30, 0x30, 0x35, 0x35, 0x30, 0x0a, 0x20, 0x20, 0x00, 0x20
+};
+
+static char EDID_Dell[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] =
+{
+       0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x5d, 0xa0, 0x55, 0x36, 0x4e, 0x32,
+       0x23, 0x14, 0x01, 0x03, 0x80, 0x35, 0x1e, 0x78, 0xee, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 
+       0x0f, 0x50, 0x54, 0xa5, 0x4b, 0x00, 0x71, 0x4f, 0x81, 0x80, 0xd1, 0xc0, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+       0x45, 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x58, 0x31, 0x37,
+       0x35, 0x52, 0x30, 0x38, 0x51, 0x32, 0x4e, 0x36, 0x55, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
+       0x45, 0x4c, 0x4c, 0x20, 0x53, 0x54, 0x32, 0x34, 0x31, 0x30, 0x0a, 0x20, 0x00, 0x00, 0x00, 0xfd,
+       0x00, 0x32, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x6d,
+       0x02, 0x03, 0x1f, 0xf1, 0x4c, 0x90, 0x05, 0x04, 0x03, 0x02, 0x07, 0x16, 0x01, 0x14, 0x1f, 0x12,
+       0x13, 0x23, 0x09, 0x07, 0x07, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x83, 0x01, 0x00, 0x00, 0x02,
+       0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00,
+       0x1e, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, 0x25, 0x00, 0x13, 0x2b, 0x21,
+       0x00, 0x00, 0x9e, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0x13,
+       0x2b, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96,
+       0x00, 0x13, 0x2b, 0x21, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b
+};
+
+static char EDID_Toshiba_32RV525RZ[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] =
+{
+       0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x5d, 0xa0, 0x55, 0x36, 0x4e, 0x32,
+       0x23, 0x14, 0x01, 0x03, 0x80, 0x35, 0x1e, 0x78, 0xee, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
+       0x0f, 0x50, 0x54, 0xa5, 0x4b, 0x00, 0x71, 0x4f, 0x81, 0x80, 0xd1, 0xc0, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+       0x45, 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x58, 0x31, 0x37,
+       0x35, 0x52, 0x30, 0x38, 0x51, 0x32, 0x4e, 0x36, 0x55, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
+       0x45, 0x4c, 0x4c, 0x20, 0x53, 0x54, 0x32, 0x34, 0x31, 0x30, 0x0a, 0x20, 0x00, 0x00, 0x00, 0xfd,
+       0x00, 0x32, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x6d,
+       0x02, 0x03, 0x1f, 0xf1, 0x4c, 0x90, 0x05, 0x04, 0x03, 0x02, 0x07, 0x16, 0x01, 0x14, 0x1f, 0x12,
+       0x13, 0x23, 0x09, 0x07, 0x07, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x83, 0x01, 0x00, 0x00, 0x02,
+       0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00,
+       0x1e, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, 0x25, 0x00, 0x13, 0x2b, 0x21,
+       0x00, 0x00, 0x9e, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0x13,
+       0x2b, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96,
+       0x00, 0x13, 0x2b, 0x21, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b
+};
+
+static char EDID_Toshiba_Regza[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] =
+{
+       0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x52, 0x62, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 
+       0x00, 0x11, 0x01, 0x03, 0x80, 0x69, 0x3b, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27, 
+       0x12, 0x48, 0x4c, 0x20, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 
+       0x45, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 
+       0x10, 0x3e, 0x96, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 
+       0x53, 0x42, 0x2d, 0x54, 0x56, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 
+       0x00, 0x17, 0x3d, 0x0f, 0x44, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x03, 
+       0x02, 0x03, 0x20, 0x77, 0x4a, 0x90, 0x05, 0x04, 0x03, 0x07, 0x02, 0x06, 0x01, 0x20, 0x22, 0x23, 
+       0x09, 0x07, 0x07, 0x6c, 0x03, 0x0c, 0x00, 0x30, 0x00, 0x00, 0x1e, 0xc0, 0x2b, 0x2b, 0x33, 0x33, 
+       0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0xc4, 0x8e, 0x21, 0x00, 
+       0x00, 0x1e, 0x8c, 0x0a, 0xa0, 0x14, 0x51, 0xf0, 0x16, 0x00, 0x26, 0x7c, 0x43, 0x00, 0xc4, 0x8e, 
+       0x21, 0x00, 0x00, 0x98, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 
+       0x13, 0x8e, 0x21, 0x00, 0x00, 0x18, 0x8c, 0x0a, 0xa0, 0x14, 0x51, 0xf0, 0x16, 0x00, 0x26, 0x7c, 
+       0x43, 0x00, 0x13, 0x8e, 0x21, 0x00, 0x00, 0x98, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 
+       0x58, 0x2c, 0x25, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3 
+};
+
+static struct hdmi_edid_info mdfld_hdmi_edid[] = {
+       { HDMI_EDID_INFO("SAMSUNG", EDID_Samsung) },
+       { HDMI_EDID_INFO("SAMSUNG_2493HM", EDID_Samsung_2493HM) },
+       { HDMI_EDID_INFO("DELL", EDID_Dell) },
+       { HDMI_EDID_INFO("TOSHIBA_32RV525RZ", EDID_Toshiba_32RV525RZ) },
+       { HDMI_EDID_INFO("TOSHIBA_REGZA", EDID_Toshiba_Regza) },
+};
+
+#if 1 /*FIXME_MDFLD_HDMI remove it later */    
+static void mdfld_hdmi_mode_set(struct drm_encoder *encoder,
+                               struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+       u32 hdmib, hdmi_phy_misc;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       /* Set panel fitting. */
+       if ((adjusted_mode->hdisplay != mode->hdisplay)
+                        || (adjusted_mode->vdisplay != mode->vdisplay))
+               REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | PFIT_PIPE_SELECT_B);
+
+       hdmib = REG_READ(hdmi_priv->hdmib_reg) | HDMIB_PORT_EN | HDMIB_PIPE_B_SELECT | HDMIB_NULL_PACKET;
+       hdmi_phy_misc = REG_READ(HDMIPHYMISCCTL) & ~HDMI_PHY_POWER_DOWN; 
+
+       REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc);
+       REG_WRITE(hdmi_priv->hdmib_reg, hdmib);
+       REG_READ(hdmi_priv->hdmib_reg);
+}
+
+static bool mdfld_hdmi_mode_fixup(struct drm_encoder *encoder,
+                                 struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(encoder->crtc);
+       PSB_DEBUG_ENTRY("hdisplay = %d, vdisplay = %d. a_hdisplay = %d, a_vdisplay = %d.\n", mode->hdisplay, mode->vdisplay, adjusted_mode->hdisplay, adjusted_mode->vdisplay);
+
+       /* Should never happen!! */
+       if (psb_intel_crtc->pipe != 1) {
+               printk(KERN_ERR
+                      "Only support HDMI on pipe B on MID \n");
+       }
+
+       /* FIXME: To make HDMI display with 1920x1080, 
+       * in 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD) fixed mode. */
+       if ((mode->hdisplay == 864 && mode->vdisplay == 480)
+                      || (mode->hdisplay == 854 && mode->vdisplay == 480)
+                      || (mode->hdisplay == 480 && mode->vdisplay == 864)
+                      || (mode->hdisplay == 480 && mode->vdisplay == 854)) {
+              adjusted_mode->hdisplay = 1920;
+              adjusted_mode->htotal = 2200;
+              adjusted_mode->hsync_start = 2008;
+              adjusted_mode->hsync_end = 2052;
+              adjusted_mode->hskew = 0;
+              adjusted_mode->vdisplay = 1080;
+              adjusted_mode->vtotal = 1125;
+              adjusted_mode->vsync_start = 1084;
+              adjusted_mode->vsync_end = 1089;
+              adjusted_mode->vscan = 0;
+              adjusted_mode->clock = 148500;
+
+              /* Apply the adjusted mode to CRTC mode setting parameters. */
+              drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+       }
+
+#if 0 /* MDFLD_HDMI_JLIU7_HACKS */
+       if (mode->hdisplay == 864 && mode->vdisplay == 480) { 
+               adjusted_mode->hdisplay = 0x500;
+               adjusted_mode->htotal = 0x672;
+               adjusted_mode->hsync_start = 0x56e;
+               adjusted_mode->hsync_end = 0x596;
+               adjusted_mode->vdisplay = 0x2d0; 
+               adjusted_mode->vtotal = 0x2ee;
+               adjusted_mode->vsync_start = 0x2d5;
+               adjusted_mode->vsync_end = 0x2da;
+               drm_mode_set_crtcinfo(adjusted_mode,
+                               CRTC_INTERLACE_HALVE_V);
+       }
+#endif /* MDFLD_HDMI_JLIU7_HACKS */ /* Debug HDMI - Can't enalbe HDMI */
+#if 0 // MDFLD_HDMI_JLIU7_HACKS /* Debug HDMI - Can't enalbe HDMI */
+#if 1 /* 720p - Adeel */
+       adjusted_mode->hdisplay = 0x500;
+       adjusted_mode->htotal = 0x672;
+       adjusted_mode->hsync_start = 0x56e;
+       adjusted_mode->hsync_end = 0x596;
+       adjusted_mode->vdisplay = 0x2d0; 
+       adjusted_mode->vtotal = 0x2ee;
+       adjusted_mode->vsync_start = 0x2d5;
+       adjusted_mode->vsync_end = 0x2da;
+#endif
+
+#if 0 /* 1080p - Brian */
+       adjusted_mode->hdisplay = 0x780;
+       adjusted_mode->htotal = 0x898;
+       adjusted_mode->hsync_start = 0x7d8;
+       adjusted_mode->hsync_end = 0x804;
+       adjusted_mode->vdisplay = 0x438; 
+       adjusted_mode->vtotal = 0x464;
+       adjusted_mode->vsync_start = 0x43c;
+       adjusted_mode->vsync_end = 0x446;
+#endif
+#if 0 /* 1080p - Adeel */
+       adjusted_mode->hdisplay = 0x780;
+       adjusted_mode->htotal = 0xabe;
+       adjusted_mode->hsync_start = 0x9fe;
+       adjusted_mode->hsync_end = 0xa2a;
+       adjusted_mode->vdisplay = 0x438; 
+       adjusted_mode->vtotal = 0x465;
+       adjusted_mode->vsync_start = 0x43c;
+       adjusted_mode->vsync_end = 0x441;
+#endif
+
+
+#if 0 /* 480p - Adeel */
+       adjusted_mode->hdisplay = 0x280;
+       adjusted_mode->htotal = 0x320;
+       adjusted_mode->hsync_start = 0x290;
+       adjusted_mode->hsync_end = 0x2f0;
+       adjusted_mode->vdisplay = 0x1e0; 
+       adjusted_mode->vtotal = 0x20d;
+       adjusted_mode->vsync_start = 0x1ea;
+       adjusted_mode->vsync_end = 0x1ec;
+#endif
+
+#if 0 /* 480p - icdk */
+       adjusted_mode->hdisplay = 0x280;
+       adjusted_mode->htotal = 0x35a;
+       adjusted_mode->hsync_start = 0x2e0;
+       adjusted_mode->hsync_end = 0x31e;
+       adjusted_mode->vdisplay = 0x1e0; 
+       adjusted_mode->vtotal = 0x20e;
+       adjusted_mode->vsync_start = 0x1ea;
+       adjusted_mode->vsync_end = 0x1ec;
+#endif
+#if 0 /* 720p - Adeel */
+               REG_WRITE(htot_reg, 0x067104ff); 
+               REG_WRITE(hblank_reg, 0x067104ff);
+               REG_WRITE(hsync_reg, 0x0595056d); 
+               REG_WRITE(vtot_reg, 0x02ed02cf);
+               REG_WRITE(vblank_reg, 0x02ed02cf);
+               REG_WRITE(vsync_reg, 0x02d902d4);
+#endif
+#if 0 /* 1080p - Brian */
+               REG_WRITE(htot_reg, 0x0897077f); 
+               REG_WRITE(hblank_reg, 0x0897077f);
+               REG_WRITE(hsync_reg, 0x080307d7); 
+               REG_WRITE(vtot_reg, 0x04630437);
+               REG_WRITE(vblank_reg, 0x04630437);
+               REG_WRITE(vsync_reg, 0x0445043b);
+#endif
+
+#if 0 /* 1080p - Adeel */
+               REG_WRITE(htot_reg, 0x0abd077f); 
+               REG_WRITE(hblank_reg, 0x0abd077f);
+               REG_WRITE(hsync_reg, 0x0a2909fd); 
+               REG_WRITE(vtot_reg, 0x04640437);
+               REG_WRITE(vblank_reg, 0x04640437);
+               REG_WRITE(vsync_reg, 0x0440043b);
+#endif
+
+
+#if 0 /* 480p - Adeel */
+               REG_WRITE(htot_reg, 0x031f027f); 
+               REG_WRITE(hblank_reg, 0x031f027f);
+               REG_WRITE(hsync_reg, 0x02ef028f); 
+               REG_WRITE(vtot_reg, 0x020c01df);
+               REG_WRITE(vblank_reg, 0x020c01df);
+               REG_WRITE(vsync_reg, 0x01eb01e9);
+#endif
+
+#if 0 /* 480p - icdk */
+               REG_WRITE(htot_reg, 0x0359027f); 
+               REG_WRITE(hblank_reg, 0x0359027f);
+               REG_WRITE(hsync_reg, 0x031d02df); 
+               REG_WRITE(vtot_reg, 0x020d01df);
+               REG_WRITE(vblank_reg, 0x020d01df);
+               REG_WRITE(vsync_reg, 0x01eb01e9);
+#endif
+       drm_mode_set_crtcinfo(adjusted_mode,
+                       CRTC_INTERLACE_HALVE_V);
+#endif /* MDFLD_HDMI_JLIU7_HACKS */ /* Debug HDMI - Can't enalbe HDMI */
+       return true;
+}
+
+
+static void mdfld_hdmi_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+       u32 hdmib, hdmi_phy_misc;
+
+       PSB_DEBUG_ENTRY("%s \n", mode == DRM_MODE_DPMS_ON ? "on" : "off");
+
+       hdmib = REG_READ(hdmi_priv->hdmib_reg) | HDMIB_PIPE_B_SELECT | HDMIB_NULL_PACKET;
+       hdmi_phy_misc = REG_READ(HDMIPHYMISCCTL);
+
+       if (mode != DRM_MODE_DPMS_ON) {
+               REG_WRITE(hdmi_priv->hdmib_reg, hdmib & ~HDMIB_PORT_EN);
+               REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc | HDMI_PHY_POWER_DOWN);
+       } else {
+               REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc & ~HDMI_PHY_POWER_DOWN);
+               REG_WRITE(hdmi_priv->hdmib_reg, hdmib | HDMIB_PORT_EN);
+       }
+       REG_READ(hdmi_priv->hdmib_reg);
+}
+
+static void mdfld_hdmi_save(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct psb_intel_output *output = to_psb_intel_output(connector);
+       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmib_reg);
+}
+
+static void mdfld_hdmi_restore(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct psb_intel_output *output = to_psb_intel_output(connector);
+       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       REG_WRITE(hdmi_priv->hdmib_reg, hdmi_priv->save_HDMIB);
+       REG_READ(hdmi_priv->hdmib_reg);
+}
+
+/* HDMI DIP related stuff */
+static int mdfld_hdmi_get_cached_edid_block(struct drm_connector *connector, uint32_t num_block, uint8_t *edid_block, uint32_t size)
+{
+    struct drm_display_info *displayinfo = &(connector->display_info);
+    if (num_block >= MAX_EDID_BLOCKS)
+    {
+       DRM_ERROR("mdfld_hdmi_get_cached_edid_block() - Invalid EDID block\n");
+        return 0; 
+    }
+    edid_block = &displayinfo->raw_edid[EDID_BLOCK_SIZE*num_block];
+    return 1;
+}
+
+/////////////////////////////////////////////////////////////////////////
+//    INTHDMIENCODER_CreateEELDPacket():
+//    This function parses v1.3 base EDID and CEA-861b EDID Timing Extension
+//    Version3 and creates EELD (Enhanced EDID Like Data) packet. This EELD data contains
+//    audio configuration information and other details read EDID.This can also contain Vendor specific Data
+//
+/////////////////////////////////////////////////////////////////////////
+static int mdfld_hdmi_create_eeld_packet(struct drm_connector *connector)
+{
+    struct psb_intel_output *output = to_psb_intel_output(connector);
+    struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+    uint8_t ucEdidBlock[128];
+    hdmi_eeld_t *pEEld                = NULL;
+    baseedid_1_x_t *pEdid        = NULL;
+    ce_edid_t *pCeEdid        = NULL;
+    int dwNumOfBytes        = 0;
+    int sizeOfCEADataBlock    = 0;
+    uint8_t * pDataBlock        = NULL;
+    edid_dtd_timing_t *pDTD    = NULL;
+    uint8_t *pData            = NULL;
+    uint8_t ucDataBlockTag    = 0;
+    cea_861b_adb_t *pADB        = NULL;
+    uint8_t i                    = 0;
+    uint8_t j                    = 0;
+    uint8_t * pSADBlocks = NULL;
+    uint8_t * pCurrentSADBlocks = NULL;
+    uint32_t ulNumSADBytes = 0;
+    //vsdb_byte6_to_byte8_t *pVSDB = NULL;
+    uint32_t ulIndex = 0;
+    //uint8_t b48kHzCADPresent = false;
+
+    pEEld = (hdmi_eeld_t *) &hdmi_priv->eeld;
+
+    // Fill Version info
+    pEEld->cea_edid_rev_id = HDMI_EELD_CEA_EDID_VERSION;
+    pEEld->eld_ver = HDMI_EELD_VERSION;
+
+    // Fill BaseLine ELD length
+    // This is 80 bytes as per EELD proposal
+    pEEld->baseline_eld_length = HDMI_EELD_BASELINE_DATA_LENGTH;
+
+    //Zero out EDID block buffer
+    memset(ucEdidBlock, 0, sizeof(ucEdidBlock));
+
+    // Get Extn EDID
+    if(!mdfld_hdmi_get_cached_edid_block(connector, 1, ucEdidBlock, EDID_BLOCK_SIZE))
+    {
+        return 0;
+    }    
+
+    pCeEdid = (ce_edid_t *) ucEdidBlock;
+
+    //allocate memory (48 bytes) for SAD Blocks buffer
+    pSADBlocks = kcalloc(1, 48, GFP_KERNEL);
+
+    if(pSADBlocks == NULL)
+    {
+       DRM_ERROR("mdfld_hdmi_create_eld_packaet() - Failed to allocate mem for pSADBlocks\n");
+        return 0;
+    }
+
+    pCurrentSADBlocks = pSADBlocks;
+
+    // Now pull out data from CEA Extension EDID
+    // If Offset <= 4, we will not have CEA DataBlocks
+    if(pCeEdid->ucDTDOffset > CEA_EDID_HEADER_SZIE)
+    {
+        sizeOfCEADataBlock = pCeEdid->ucDTDOffset - CEA_EDID_HEADER_SZIE;
+
+        pDataBlock = (uint8_t *)pCeEdid;
+
+        // skip header (first 4 bytes) in CEA EDID Timing Extension
+        // and set pointer to start of DataBlocks collection
+        pDataBlock += CEA_EDID_HEADER_SZIE;
+
+        // General Format of CEA Data Block Collection
+        // -----------+--------------------+-----------------------------------------+
+        //            |Byte#   |bits5-7    |       bits 0-4                          |
+        // -----------|--------------------+-----------------------------------------+
+        //            |  1     | Video Tag |Length = total #of video bytes following |
+        //            |        |    Code   |this byte (L1)                           |
+        //            |--------------------+-----------------------------------------+
+        //  Video     |  2     | CEA Short Video Descriptor 1                        |
+        //  Data      |--------+-----------------------------------------------------|
+        //  Block     |  3     | CEA Short Video Descriptor 2                        |
+        //            |--------+-----------------------------------------------------|
+        //            | ...    | ...                                                 |
+        //            |--------------------------------------------------------------+
+        //            | 1+L1   | CEA Short Video Descriptor L1                       |
+        // -----------+--------------------+-----------------------------------------+
+        //            | 2+L1   | Audio Tag |Length = total #of audio bytes following |
+        //            |        |    Code   |this byte (L2)                           |
+        //            |--------------------+-----------------------------------------+
+        //  Audio     | 3+L1   |                                                     |
+        //  Data      |--------+                                                     |
+        //  Block     | 4+L1   | CEA Short Audio Descriptor 1                        |
+        //            |--------+                                                     |
+        //            | 5+L1   |                                                     |
+        //            |--------------------------------------------------------------+
+        //            | ...    |                                                     |
+        //            |        |                                                     |
+        //            |        |                                                     |
+        //            | ...    |                                                     |
+        //            |---------------------------------------------------------------
+        //            |L1+L2   |                                                     |
+        //            |--------|                                                     |
+        //            |1+L1+L2 | CEA Short Audio Descriptor L2/3                     |
+        //            |--------|                                                     |
+        //            |2+L1+L2 |                                                     |
+        // -----------+--------------------------------------------------------------+
+        //            |3+L1+L2 |  Speaker  |Length = total #of SA bytes following    |
+        //            |        | Tag Code  |this byte (L1)                           |
+        //  Speaker   |--------------------------------------------------------------+
+        //  Allocation|4+L1+L2 |                                                     |
+        //  Data      |--------|                                                     |
+        //  Block     |5+L1+L2 | Speaker Allocation Data Block Payload(3 bytes)      |
+        //            |--------|                                                     |
+        //            |6+L1+L2 |                                                     |
+        // -----------+--------------------------------------------------------------+
+        //            |7+L1+L2 | VSDB  Tag |Length = total #of VSDB bytes following  |
+        //            |        |    Code   |this byte (L1)                           |
+        //  Vendor    |--------------------------------------------------------------+
+        //  Specific  |8+L1+L2 |                                                     |
+        //  Data      |--------|                                                     |
+        //  Block     |9+L1+L2 | 24-bit IEEE Registration Identifier (LSB first)     |
+        //            |--------|                                                     |
+        //            |10+L1+L2|                                                     |
+        //            |--------------------------------------------------------------+
+        //            | ...    | Vendor Specific Data block Payload                  |
+        // -----------+--------------------------------------------------------------+
+
+        while(sizeOfCEADataBlock > 0)
+        {
+            // Get the Size of CEA DataBlock in bytes and TAG
+            dwNumOfBytes = *pDataBlock & CEA_DATABLOCK_LENGTH_MASK;
+            ucDataBlockTag = (*pDataBlock & CEA_DATABLOCK_TAG_MASK) >> 5;
+
+            switch(ucDataBlockTag)
+            {
+                case CEA_AUDIO_DATABLOCK:
+                    // move beyond tag/length byte
+                    ++pDataBlock;
+                    for (i = 0; i < (dwNumOfBytes / 3); ++i, pDataBlock += 3)
+                    {
+                        pADB = (cea_861b_adb_t*)pDataBlock;
+                        switch(pADB->audio_format_code)
+                        {
+                            // uncompressed audio (Linear PCM)
+                            case AUDIO_LPCM:
+                                memcpy(&(hdmi_priv->lpcm_sad),pDataBlock,3);
+                                //save these blocks
+                                memcpy(pCurrentSADBlocks, pDataBlock, 3);
+                                // move pointer in SAD blocks buffer
+                                pCurrentSADBlocks += 3;
+                                // update SADC field
+                                pEEld->sadc += 1;
+                                break;
+                            // compressed audio
+                            case AUDIO_AC3:
+                            case AUDIO_MPEG1:
+                            case AUDIO_MP3:
+                            case AUDIO_MPEG2:
+                            case AUDIO_AAC:
+                            case AUDIO_DTS:
+                            case AUDIO_ATRAC:
+                            case AUDIO_OBA:
+                            case AUDIO_DOLBY_DIGITAL:
+                            case AUDIO_DTS_HD:
+                            case AUDIO_MAT:
+                            case AUDIO_DST:
+                            case AUDIO_WMA_PRO:
+                                //save these blocks
+                                memcpy(pCurrentSADBlocks, pDataBlock, 3);
+                                // move pointer in SAD blocks buffer
+                                pCurrentSADBlocks += 3;
+                                // update SADC field
+                                pEEld->sadc += 1;
+                                break;
+                        }
+                    }
+                    break;
+
+                case CEA_VENDOR_DATABLOCK:
+                    // audio wants data from 6th byte of VSDB onwards
+                    //Sighting 94842: 
+
+                    // | Byte # |    bits[7-0]                                              |
+                    // |--------------------------------------------------------------------|
+                    // | 1-3    |24-bit IEEE Registration Identifier (0x000C03)             |
+                    // |--------------------------------------------------------------------|
+                    // | 4-5    |       Source Physical Address                             |
+                    // |--------------------------------------------------------------------|
+                    // | 6      |SupportsAI|DC48bit|DC36bit|Dc30bit|DCY444|Rsvd|Rsvd|DVIDual|
+                    // |--------------------------------------------------------------------|
+                    // | 7      |   Max TMDS clock                                          |
+                    // |--------------------------------------------------------------------|
+                    // | 8      |Latency_Field |I_Latency_Field| Reserved bits 5-0          |
+                    // |        |   _Present   |  _Present     |                            |
+                    // |--------------------------------------------------------------------|
+                    // | 9      |               Video Latency                               |
+                    // |--------------------------------------------------------------------|
+                    // | 10     |               Audio Latency                               |
+                    // |--------------------------------------------------------------------|
+                    // | 11     |            Interlaced Video Latency                       |
+                    // |--------------------------------------------------------------------|
+                    // | 12     |            Interlaced Audio Latency                       |
+                    // |--------------------------------------------------------------------|
+
+                    ++pDataBlock;
+                    // move pointer to next CEA Datablock
+                    pDataBlock += dwNumOfBytes;
+                    break;                 
+
+                case CEA_SPEAKER_DATABLOCK:
+                    pEEld->speaker_allocation_block = *(++pDataBlock);
+                    // move pointer to next CEA Datablock
+                    pDataBlock += dwNumOfBytes;
+                    break;                       
+
+                default:
+                    // Move pointer to next CEA DataBlock
+                    pDataBlock += (dwNumOfBytes + 1);
+            }
+            // Decrement size of CEA DataBlock
+            sizeOfCEADataBlock -= (dwNumOfBytes + 1);
+        }    
+    }
+
+    //Copy all the saved SAD blocks at the end of ELD
+    //SAD blocks should be written after the Monitor name and VSDB.
+    //See ELD definition in iHDMI.h
+    ulNumSADBytes = (pEEld->sadc) * 3; //Size of each SAD block is 3 bytes
+
+    //DCN 460119: Audio does not play on displays which do not provide SAB in EDID.
+    //Solution: Graphics driver should create a default SAB in ELD with front left and front right
+    //speakers enabled if the display supports basic audio. 
+    pDataBlock = (uint8_t *)pCeEdid;
+    if((*(pDataBlock + HDMI_CEA_EXTENSION_BLOCK_BYTE_3) & HDMI_BASIC_AUDIO_SUPPORTED) && (pEEld->speaker_allocation_block == 0)) 
+    {
+        pEEld->flr = 1;
+    }
+    //End of DCN 460119
+
+    // zero out local buffers
+    memset(ucEdidBlock, 0, sizeof(ucEdidBlock));
+
+    // Get base EDID
+    if(!mdfld_hdmi_get_cached_edid_block(connector, 0, ucEdidBlock, EDID_BLOCK_SIZE))
+    {
+        return 0;
+    }
+
+    pEdid = (baseedid_1_x_t*) ucEdidBlock;
+    pDTD = &pEdid->DTD[1];
+
+    //Update the Manufacturer ID and Product Code here
+    memcpy(pEEld->manufacturer_id,pEdid->ManufacturerID,2);
+    memcpy(pEEld->product_id,pEdid->ProductID,2);
+
+    // Now Fill the monitor string name
+    // Search through DTD blocks, looking for monitor name
+    for (i = 0; i < MAX_BASEEDID_DTD_BLOCKS - 1; ++i, ++pDTD)
+    {
+        // Set a uint8_t pointer to DTD data
+        pData = (uint8_t *)pDTD;
+
+        // Check the Flag (the first two bytes) to determine
+        // if this block is used as descriptor
+        if (pData[0] == 0x00 && pData[1] == 0x00)
+        {
+            // And now check Data Type Tag within this descriptor
+            // Tag = 0xFC, then monitor name stored as ASCII
+            if (pData[3] == 0xFC)
+            {
+                ulIndex = 0;
+                // Copy monitor name
+                for (j = 0; (j < 13) && (pData[j+5] != 0x0A); ++j)
+                {
+                    pEEld->mn_sand_sads[ulIndex] = pData[j+5];
+                    ulIndex++;
+                }
+                pEEld->mnl = j;
+                break;
+            }
+        }
+    }
+
+    //Check if number of SAD Bytes > 0 and for size within limits of allowed Base line Data size as per EELD spec
+    if((ulNumSADBytes > 0) && (ulNumSADBytes <= 64))
+    {
+        //Copy the SADs immediately after the Monitor Name String
+        memcpy(&pEEld->mn_sand_sads[j], pSADBlocks, ulNumSADBytes);
+    }
+
+
+    // Header = 4, Baseline Data = 60 and Vendor (INTEL) specific = 2
+    // 4 + 60 + 2 = 66
+    hdmi_priv->hdmi_eeld_size = HDMI_EELD_SIZE;
+    
+    //free the buffer allocated for SAD blocks
+    kfree(pSADBlocks);
+    pSADBlocks = NULL;
+    pCurrentSADBlocks = NULL;
+    return 1;
+}
+
+static enum drm_connector_status
+mdfld_hdmi_edid_detect(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct psb_intel_output *output = to_psb_intel_output(connector);
+       struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+       struct edid *edid = NULL;
+       enum drm_connector_status status = connector_status_disconnected;
+       int i = 0;
+       int monitor_number = sizeof(mdfld_hdmi_edid) / sizeof(struct hdmi_edid_info);
+
+       PSB_DEBUG_ENTRY("\n");
+
+#if 0
+       if (!psb_intel_output->hdmi_i2c_adapter) {
+               DRM_INFO("Enter mdfld_hdmi_get_modes, i2c_adapter is NULL. \n");
+               
+               /* hard-coded the HDMI_I2C_ADAPTER_ID to be 3, Should get from GCT*/
+               psb_intel_output->hdmi_i2c_adapter = i2c_get_adapter(3);
+       }
+
+       if (!psb_intel_output->hdmi_i2c_adapter) {
+               DRM_INFO("Enter mdfld_hdmi_get_modes, no valid i2c_adapter . \n");
+               return ret;
+       }
+
+       edid =
+           drm_get_edid(&psb_intel_output->base,
+                        psb_intel_output->hdmi_i2c_adapter);
+
+       hdmi_priv->has_hdmi_sink = false;
+       if (edid) {
+               if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+                       status = connector_status_connected;
+                       hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+                       mdfld_hdmi_create_eeld_packet(connector);
+               }
+
+               intel_output->base.display_info.raw_edid = NULL;
+               kfree(edid);
+       }
+#else
+       if ((HDMI_EDID == NULL) || (strlen(HDMI_EDID) > HDMI_MONITOR_NAME_LENGTH))
+               return status;
+
+       DRM_INFO("Detected HDMI monitor %s.\n", HDMI_EDID);
+
+       for (i = 0; i < monitor_number; i++) {
+               if (!strcasecmp(HDMI_EDID, mdfld_hdmi_edid[i].monitor_name)) {
+                       edid = (struct edid *)mdfld_hdmi_edid[i].edid_info;
+                       break;
+               }
+       }
+
+       if (i == monitor_number)
+               edid = (struct edid *)mdfld_hdmi_edid[monitor_number - 1].edid_info;
+
+       hdmi_priv->has_hdmi_sink = false;
+       if (edid) {
+               status = connector_status_connected;
+               hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+               mdfld_hdmi_create_eeld_packet(connector);
+       }
+
+       dev_priv->hdmi_done_reading_edid = true;
+#endif 
+       return status;
+}
+
+/* FIXME: start using the force parameter */
+static enum drm_connector_status mdfld_hdmi_detect(struct drm_connector
+                                               *connector, bool force)
+{
+       return mdfld_hdmi_edid_detect(connector);
+}
+
+static int mdfld_hdmi_set_property(struct drm_connector *connector,
+                                      struct drm_property *property,
+                                      uint64_t value)
+{
+       struct drm_encoder *pEncoder = connector->encoder;
+
+       PSB_DEBUG_ENTRY("connector info, type = %d, type_id=%d, base=0x%p, base.id=0x%x. \n", connector->connector_type, connector->connector_type_id, &connector->base, connector->base.id);
+       PSB_DEBUG_ENTRY("encoder info, base.id=%d, encoder_type=%d, dev=0x%p, base=0x%p, possible_clones=0x%x. \n", pEncoder->base.id, pEncoder->encoder_type, pEncoder->dev, &pEncoder->base, pEncoder->possible_clones);
+       PSB_DEBUG_ENTRY("encoder info, possible_crtcs=0x%x, crtc=0x%p.  \n", pEncoder->possible_crtcs, pEncoder->crtc);
+
+       if (!strcmp(property->name, "scaling mode") && pEncoder) {
+               PSB_DEBUG_ENTRY("scaling mode \n");
+       } else if (!strcmp(property->name, "backlight") && pEncoder) {
+               PSB_DEBUG_ENTRY("backlight \n");
+       } else if (!strcmp(property->name, "DPMS") && pEncoder) {
+               PSB_DEBUG_ENTRY("DPMS \n");
+       }
+
+       if (!strcmp(property->name, "scaling mode") && pEncoder) {
+               struct psb_intel_crtc *pPsbCrtc = to_psb_intel_crtc(pEncoder->crtc);
+               bool bTransitionFromToCentered;
+               uint64_t curValue;
+
+               if (!pPsbCrtc)
+                       goto set_prop_error;
+
+               switch (value) {
+               case DRM_MODE_SCALE_FULLSCREEN:
+                       break;
+               case DRM_MODE_SCALE_NO_SCALE:
+                       break;
+               case DRM_MODE_SCALE_ASPECT:
+                       break;
+               default:
+                       goto set_prop_error;
+               }
+
+               if (drm_connector_property_get_value(connector, property, &curValue))
+                       goto set_prop_error;
+
+               if (curValue == value)
+                       goto set_prop_done;
+
+               if (drm_connector_property_set_value(connector, property, value))
+                       goto set_prop_error;
+
+               bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
+                       (value == DRM_MODE_SCALE_NO_SCALE);
+
+               if (pPsbCrtc->saved_mode.hdisplay != 0 &&
+                   pPsbCrtc->saved_mode.vdisplay != 0) {
+                       if (bTransitionFromToCentered) {
+                               if (!drm_crtc_helper_set_mode(pEncoder->crtc, &pPsbCrtc->saved_mode,
+                                           pEncoder->crtc->x, pEncoder->crtc->y, pEncoder->crtc->fb))
+                                       goto set_prop_error;
+                       } else {
+                               struct drm_encoder_helper_funcs *pEncHFuncs  = pEncoder->helper_private;
+                               pEncHFuncs->mode_set(pEncoder, &pPsbCrtc->saved_mode,
+                                                    &pPsbCrtc->saved_adjusted_mode);
+                       }
+               }
+       } 
+set_prop_done:
+    return 0;
+set_prop_error:
+    return -1;
+}
+
+/**
+ * Return the list of HDMI DDC modes if available.
+ */
+static int mdfld_hdmi_get_modes(struct drm_connector *connector)
+{
+       struct psb_intel_output *psb_intel_output = to_psb_intel_output(connector);
+       struct edid *edid = NULL;
+       int ret = 0;
+#if 1 /* FIXME_JLIU7 HDMI*/    
+       struct drm_device *dev = connector->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct mdfld_dsi_config *dsi_config = dev_priv->dsi_configs[0];
+       struct drm_display_mode *panel_fixed_mode = NULL;
+#endif 
+       int i = 0;
+       int monitor_number = sizeof(mdfld_hdmi_edid) / sizeof(struct hdmi_edid_info);
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if (dsi_config != NULL) {
+               panel_fixed_mode
+                        = drm_mode_duplicate(dev, dsi_config->fixed_mode);
+       }
+
+#if 0
+       if (!psb_intel_output->hdmi_i2c_adapter) {
+               DRM_INFO("Enter mdfld_hdmi_get_modes, i2c_adapter is NULL. \n");
+               
+               /* hard-coded the HDMI_I2C_ADAPTER_ID to be 3, Should get from GCT*/
+               psb_intel_output->hdmi_i2c_adapter = i2c_get_adapter(3);
+       }
+
+       if (!psb_intel_output->hdmi_i2c_adapter) {
+               DRM_INFO("Enter mdfld_hdmi_get_modes, no valid i2c_adapter . \n");
+               return ret;
+       }
+
+       edid =
+           drm_get_edid(&psb_intel_output->base,
+                        psb_intel_output->hdmi_i2c_adapter);
+#else
+       edid = NULL;
+#endif 
+       if (edid) {
+               drm_mode_connector_update_edid_property(&psb_intel_output->
+                                                       base, edid);
+               ret = drm_add_edid_modes(&psb_intel_output->base, edid);
+               kfree(edid);
+       }
+#if MDFLD_HDMI_JLIU7_DEBUG_1
+       else {
+               DRM_INFO("mdfld_hdmi_get_modes, fake edid info. \n");
+#if 1 //MDFLD_HDMI_JLIU7_DEBUG_1
+               for (i = 0; i < monitor_number; i++) {
+                       if (!strcasecmp(HDMI_EDID, mdfld_hdmi_edid[i].monitor_name)) {
+                               edid = (struct edid *)mdfld_hdmi_edid[i].edid_info;
+                               break;
+                       }
+               }
+
+               if (i == monitor_number)
+                       edid = (struct edid *)mdfld_hdmi_edid[monitor_number - 1].edid_info;
+
+               connector->display_info.raw_edid = (char *)edid;
+               drm_mode_connector_update_edid_property(&psb_intel_output->
+                                                       base, edid);
+               ret = drm_add_edid_modes(&psb_intel_output->base, edid);
+#if 1 /* FIXME_JLIU7 HDMI*/    
+       if (panel_fixed_mode != NULL) {
+               struct drm_display_mode *mode =
+                   drm_mode_duplicate(dev, panel_fixed_mode);
+               drm_mode_probed_add(connector, mode);
+       }
+#endif /* FIXME_JLIU7 HDMI*/   
+#endif /* MDFLD_HDMI_JLIU7_DEBUG_1 */
+       }
+#endif /* MDFLD_HDMI_JLIU7_DEBUG_1 */
+
+       if (ret)
+               return ret;
+
+       /* Didn't get an EDID, so
+        * Set wide sync ranges so we get all modes
+        * handed to valid_mode for checking
+        */
+       connector->display_info.min_vfreq = 0;
+       connector->display_info.max_vfreq = 200;
+       connector->display_info.min_hfreq = 0;
+       connector->display_info.max_hfreq = 200;
+
+       return 0;
+}
+
+static int mdfld_hdmi_mode_valid(struct drm_connector *connector,
+                                struct drm_display_mode *mode)
+{
+
+       PSB_DEBUG_ENTRY("display info. hdisplay = %d, vdisplay = %d. \n", mode->hdisplay, mode->vdisplay);
+
+#if 0 /* MDFLD_HDMI_JLIU7_DEBUG */
+       if (mode->clock > 165000)
+               return MODE_CLOCK_HIGH;
+       if (mode->clock < 20000)
+               return MODE_CLOCK_HIGH;
+#endif /* MDFLD_HDMI_JLIU7_DEBUG */
+
+       /* just in case */
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               return MODE_NO_DBLESCAN;
+
+       /* just in case */
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+               return MODE_NO_INTERLACE;
+
+#if !MDFLD_HDMI_JLIU7_1080
+       if (mode->hdisplay > 1600)
+               return MODE_PANEL;
+       if (mode->vdisplay > 1080)
+               return MODE_PANEL;
+#endif /* MDFLD_HDMI_JLIU7_1080 */
+
+       return MODE_OK;
+}
+
+static void mdfld_hdmi_connector_dpms(struct drm_connector *connector, int mode)
+{
+#ifdef CONFIG_PM_RUNTIME
+       struct drm_device * dev = connector->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       bool panel_on, panel_on2;
+#endif
+       /*first, execute dpms*/
+               
+       drm_helper_connector_dpms(connector, mode);
+
+#ifdef CONFIG_PM_RUNTIME       
+       if(is_panel_vid_or_cmd(dev)) {
+               /*DPI panel*/
+               panel_on = dev_priv->dpi_panel_on;
+               panel_on2 = dev_priv->dpi_panel_on2;
+       } else {
+               /*DBI panel*/
+               panel_on = dev_priv->dbi_panel_on;
+               panel_on2 = dev_priv->dbi_panel_on2;
+       }       
+       
+       /*then check all display panels + monitors status*/
+       if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN)) {
+               /*request rpm idle*/
+               if(dev_priv->rpm_enabled) {
+                       pm_request_idle(&dev->pdev->dev);
+               }
+       } 
+       
+       /**
+        * if rpm wasn't enabled yet, try to allow it
+        * FIXME: won't enable rpm for DPI since DPI
+        * CRTC setting is a little messy now. 
+        * Enable it later!
+        */
+#if 0
+       if(!dev_priv->rpm_enabled && !is_panel_vid_or_cmd(dev)) 
+               ospm_runtime_pm_allow(dev);
+#endif
+#endif         
+}
+
+/**
+ * psb_intel_lvds_destroy - unregister and free LVDS structures
+ * @connector: connector to free
+ *
+ * Unregister the DDC bus for this connector then free the driver private
+ * structure.
+ *
+ * Note: taken from psb_intel_lvds.c
+ */
+static void psb_intel_lvds_destroy(struct drm_connector *connector)
+{
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
+       kfree(connector);
+}
+
+/* Note: taken from psb_intel_lvds.c */
+static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+       drm_encoder_cleanup(encoder);
+}
+
+/* Note: taken from psb_intel_lvds.c */
+static const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
+       .destroy = psb_intel_lvds_enc_destroy,
+};
+
+static const struct drm_encoder_helper_funcs mdfld_hdmi_helper_funcs = {
+       .dpms = mdfld_hdmi_dpms,
+       .mode_fixup = mdfld_hdmi_mode_fixup,
+       .prepare = psb_intel_encoder_prepare,
+       .mode_set = mdfld_hdmi_mode_set,
+       .commit = psb_intel_encoder_commit,
+};
+
+static const struct drm_connector_helper_funcs
+    mdfld_hdmi_connector_helper_funcs = {
+       .get_modes = mdfld_hdmi_get_modes,
+       .mode_valid = mdfld_hdmi_mode_valid,
+       .best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_connector_funcs mdfld_hdmi_connector_funcs = {
+       .dpms = mdfld_hdmi_connector_dpms,
+       .save = mdfld_hdmi_save,
+       .restore = mdfld_hdmi_restore,
+       .detect = mdfld_hdmi_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .set_property = mdfld_hdmi_set_property,
+       .destroy = psb_intel_lvds_destroy,
+};
+
+void mdfld_hdmi_init(struct drm_device *dev,
+                   struct psb_intel_mode_device *mode_dev)
+{
+#if 0
+       DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+#endif 
+       struct psb_intel_output *psb_intel_output;
+       struct drm_connector *connector;
+       struct drm_encoder *encoder;
+       struct mid_intel_hdmi_priv *hdmi_priv;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
+                              sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL);
+       if (!psb_intel_output)
+               return;
+
+       hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1);
+       psb_intel_output->mode_dev = mode_dev;
+       connector = &psb_intel_output->base;
+       encoder = &psb_intel_output->enc;
+       drm_connector_init(dev, &psb_intel_output->base,
+                          &mdfld_hdmi_connector_funcs,
+                          DRM_MODE_CONNECTOR_DVID);
+
+       drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
+                        DRM_MODE_ENCODER_TMDS);
+
+       drm_mode_connector_attach_encoder(&psb_intel_output->base,
+                                         &psb_intel_output->enc);
+       psb_intel_output->type = INTEL_OUTPUT_HDMI;
+       /*FIXME: May need to get this somewhere, but CG code seems hard coded it*/
+       hdmi_priv->hdmib_reg = HDMIB_CONTROL;
+       hdmi_priv->has_hdmi_sink = false;
+       psb_intel_output->dev_priv = hdmi_priv;
+
+       drm_encoder_helper_add(encoder, &mdfld_hdmi_helper_funcs);
+       drm_connector_helper_add(connector,
+                                &mdfld_hdmi_connector_helper_funcs);
+       connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+       connector->interlace_allowed = false;
+       connector->doublescan_allowed = false;
+
+       drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
+
+       /* hard-coded the HDMI_I2C_ADAPTER_ID to be 3, Should get from GCT*/
+       psb_intel_output->hdmi_i2c_adapter = i2c_get_adapter(3);
+
+       if (psb_intel_output->hdmi_i2c_adapter) {
+               /* HACKS_JLIU7 */
+               DRM_INFO("Enter mdfld_hdmi_init, i2c_adapter is availabe.\n");
+       
+       } else {
+               printk(KERN_ALERT "No ddc adapter available!\n");
+       }
+
+       hdmi_priv->is_hdcp_supported = true;
+       hdmi_priv->hdmi_i2c_adapter = psb_intel_output->hdmi_i2c_adapter;
+       hdmi_priv->dev = dev; 
+       mdfld_hdcp_init(hdmi_priv);
+       mdfld_hdmi_audio_init(hdmi_priv);
+       mdfld_msic_init(hdmi_priv);
+
+       drm_sysfs_connector_add(connector);
+       return;
+}
+#endif
diff --git a/drivers/staging/mrst/drv/psb_intel_hdmi.h b/drivers/staging/mrst/drv/psb_intel_hdmi.h
new file mode 100644 (file)
index 0000000..23e3583
--- /dev/null
@@ -0,0 +1,937 @@
+/*
+ * Copyright Â© 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Chunfeng Zhao <chunfeng.zhao@intel.com>
+ *     Jim Liu <jim.liu@intel.com>
+ */
+
+#ifndef __PSB_INTEL_HDMI_H__
+#define __PSB_INTEL_HDMI_H__
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+/*
+ * HDMI Parameters
+ */
+
+/* GUID HDMI Parameters */
+#if 0
+//#ifdef DEFINE_GUID
+//#undef DEFINE_GUID
+#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+//#endif /* DEFINE_GUID */
+
+#define HDMI_PARAMETERS_GUID "{6FD3BE0E-80F9-4206-86B7-3714FA439634}"
+DEFINE_GUID(GUID_HDMI_PARAMETERS, 0x6fd3be0e, 0x80f9, 0x4206, 0x86, 0xb7, 0x37, 0x14, 0xfa, 0x43, 0x96, 0x34);
+
+#define AVI_INFOFRAME_GUID "{DFCB113B-E54F-49A2-B5E3-78D0C6B4F4CB}"
+DEFINE_GUID(GUID_AVI_INFOFRAME, 0xdfcb113b, 0xe54f, 0x49a2, 0xb5, 0xe3, 0x78, 0xd0, 0xc6, 0xb4, 0xf4, 0xcb);
+#endif
+
+#define HDMI_DEVICE_NAME "ABC_VEND"
+#define HDMI_DEVICE_DESC "XZ05 PC VIDEO"
+
+#define HDMI_MAX_PIXEL_REPETITION 0x04     // On Cantiga only upto 4X pixel repetition is supported
+#define HDMI_HBR_AUDIO_SAMPLE_RATE 192000  // 192kHz is the sample rate corresponding to the HBR audio formats
+#define HDMI_AUDIO_CLOCK_PACKET_RATE 1500  // Audio clock packet rate of 1.5kHz has to be considered while calculating audio BW
+
+#define HDMI_BAR_INFO_LENGTH 8 // 8 bytes of barinfo
+
+#define HDMI_MONITOR_NAME_LENGTH 20
+
+// BaseLineDataLength.
+// Total size is in multiple of 4 bytes. i.e, 80/4 = 20
+#define HDMI_EELD_BASELINE_DATA_LENGTH 0x14
+
+// Header = 4, Baseline Data = 80 and Vendor (INTEL) specific = 2 as per EELD spec
+// 4 + 80 + = 84
+#define HDMI_EELD_SIZE 84
+
+//
+// HDMI command types
+//
+typedef enum
+{
+    HDMI_COMMAND_GET,
+    HDMI_COMMAND_SET
+} hdmi_command_t;
+
+#define HDMI_AVI_FLAG_ITCONTENT 0x00800000
+#define HDMI_AVI_FLAG_RGB_QUANT_RANGE 0x00040000
+#define HDMI_AVI_FLAG_SCAN_INFO 0x00000001
+#define HDMI_AVI_FLAG_BAR_INFO 0x00000010
+//
+// CEA-861b definitions
+//
+#define HDMI_CEA_VERSION             0x00
+#define HDMI_ELD_VERSION             0x01
+#define HDMI_EELD_VERSION            0x02
+#define HDMI_BASE_ELD_SIZE           0x0E
+#define HDMI_CEA_EDID_HEADER_SIZE    0x04
+#define HDMI_EELD_CEA_EDID_VERSION   0x03
+#define HDMI_CEA_EDID_BLOCK_SIZE     128
+
+//
+//Basic Audio support definitions
+//
+
+#define HDMI_BASIC_AUDIO_SUPPORTED                0x40
+#define HDMI_CEA_EXTENSION_BLOCK_BYTE_3            3
+#define HDMI_FL_AND_FR_SPEAKERS_CONNECTED        0x1
+
+//
+// HDMI buffer/information types
+//
+typedef enum {
+    // Non-standard or non-HDMI type
+    HDMI_ELD_TYPE   = 0x00,     // ELD buffer type
+    HDMI_EELD_TYPE  = 0x01,     // EELD buffer type
+    
+    // Per HDMI Spec, refer Table 2-1 in HDMI EDS 
+    // or Table 5-8 in HDMI spec
+    HDMI_VS_TYPE    = 0x81,     // Vendor-Specific InfoFrame type
+    HDMI_AVI_TYPE   = 0x82,     // AVI InfoFrame type
+    HDMI_SPD_TYPE   = 0x83,     // SPD InfoFrame type
+    HDMI_AUDIO_TYPE = 0x84,     // Audio InfoFrame type
+    HDMI_MS_TYPE    = 0x85,     // MPEG Source InfoFrame type
+    
+    // Non-standard or non-HDMI types
+    HDMI_PR_PE_TYPE = 0x86,     // Pixel Replication & Pixel Encoding(colorimetry) type
+    HDMI_AUDIO_CAPS_TYPE = 0x87, // Encoder Audio Capabilities type
+    HDMI_AUDIO_ENABLE_FLAGS_TYPE = 0x88 // Flags for enabling / disabling audio
+} hdmi_info_type_t;
+
+//
+// InfoFrame Version Information
+//
+typedef enum {
+    HDMI_VS_VERSION    = 1,  // Vendor-Specific InfoFrame Version 1
+    HDMI_AVI_VERSION   = 1,  // AVI InfoFrame Version 1
+    HDMI_AVI_VERSION2  = 2,  // AVI InfoFrame Version 2
+    HDMI_SPD_VERSION   = 1,  // SPD InfoFrame Version 1
+    HDMI_AUDIO_VERSION = 1,  // Audio InfoFrame Version 1
+    HDMI_MS_VERSION    = 1   // MPEG Source InfoFrame Version 1
+} infoframe_version_t;
+
+//
+// InfoFrame Payload Length in bytes
+//
+typedef enum {
+    HDMI_VS_MAX_LENGTH     = 27,   // Vendor-Specific InfoFrame Payload Length, including IEEE reg ID
+    HDMI_AVI_LENGTH        = 13,  // AVI InfoFrame Payload Length
+    HDMI_SPD_LENGTH        = 25,  // SPD InfoFrame Payload Length
+    HDMI_AUDIO_LENGTH      = 10,  // Audio InfoFrame Payload Length
+    HDMI_MS_LENGTH         = 10,  // MPEG Source InfoFrame Payload Length
+    HDMI_PR_PE_LENGTH      = 4,   // Length of PR_PE_TYPE
+    HDMI_AUDIO_CAPS_LENGTH = 4    // Length of AUDIO_CAPS_TYPE
+} infoframe_length_t;
+
+//
+// InfoFrame TOTAL Length in bytes (includes header + payload)
+//
+typedef enum {
+    HDMI_VS_MAX_TOTAL_LENGTH     = HDMI_VS_MAX_LENGTH + 4,   // Max Total size of Vendor-Specific InfoFrame
+    HDMI_AVI_TOTAL_LENGTH        = HDMI_AVI_LENGTH + 4,  // Total size of AVI InfoFrame
+    HDMI_SPD_TOTAL_LENGTH        = HDMI_SPD_LENGTH + 4,  // Total size of SPD InfoFrame
+    HDMI_AUDIO_TOTAL_LENGTH      = HDMI_AUDIO_LENGTH + 4,  // Total size of Audio InfoFrame
+    HDMI_MS_TOTAL_LENGTH         = HDMI_MS_LENGTH + 4,  // Total size of MPEG Source InfoFrame
+} infoframe_total_length_t;
+
+
+//
+// Pixel Replication multipliers
+//
+typedef enum {
+    HDMI_PR_ONE = 0,    // No repetition (ie., pixel sent once)
+    HDMI_PR_TWO,        // Pixel sent 2 times (ie.,repeated once)
+    HDMI_PR_THREE,      // Pixel sent 3 times
+    HDMI_PR_FOUR,       // Pixel sent 4 times
+    HDMI_PR_FIVE,       // Pixel sent 5 times
+    HDMI_PR_SIX,        // Pixel sent 6 times
+    HDMI_PR_SEVEN,      // Pixel sent 7 times
+    HDMI_PR_EIGHT,      // Pixel sent 8 times
+    HDMI_PR_NINE,       // Pixel sent 9 times
+    HDMI_PR_TEN         // Pixel sent 10 times
+} hdmi_pixel_replication_t;
+
+//
+// Pixel encoding modes
+//
+//typedef typedef enum  {
+  //  HDMI_RGB256 = 0x01,
+  //  HDMI_RGB220 = 0x02,
+  //  HDMI_YCrCb422 = 0x04,
+  //  HDMI_YCrCb444 = 0x08
+//}HDMI_COLORIMETRY;
+
+//
+// Pixel encoding modes
+//
+typedef enum {
+    HDMI_COLORIMETRY_RGB256 = 0x01,
+    HDMI_COLORIMETRY_RGB220 = 0x02,
+    HDMI_COLORIMETRY_YCrCb422 = 0x04,
+    HDMI_COLORIMETRY_YCrCb444 = 0x08
+} hdmi_colorimetry_t;
+
+//
+// AVI InfoFrame definitions - start
+//
+// Scan Info
+typedef enum {
+    HDMI_AVI_SCAN_NODATA     = 0,     // No data
+    HDMI_AVI_SCAN_OVERSCAN   = 1,     // Overscanned (TV)
+    HDMI_AVI_SCAN_UNDERSCAN  = 2,     // Underscanned (Computer)
+    HDMI_AVI_SCAN_FUTURE     = 3      // Future
+} avi_scan_info_t;
+
+// Bar Info
+typedef enum {
+    HDMI_AVI_BAR_INVALID         = 0,      // Bar data not valid
+    HDMI_AVI_BAR_VALID_VERTICAL  = 1,      // Vertical Bar data valid
+    HDMI_AVI_BAR_VALID_HORIZONTAL= 2,      // Horizontal Bar data valid
+    HDMI_AVI_BAR_VALID_BOTH      = 3       // Vertical & Horizontal Bar data valid
+} avi_bar_info_t;
+
+// Active Format Information
+typedef enum {
+    HDMI_AVI_AFI_INVALID = 0,    // No data
+    HDMI_AVI_AFI_VALID   = 1     // Active Format Information valid
+} avi_fi_info_t;
+
+// AVI Pixel Encoding modes
+typedef enum {
+    HDMI_AVI_RGB_MODE      = 0,  // RGB pixel encoding mode
+    HDMI_AVI_YCRCB422_MODE = 1,  // YCrCb 4:2:2 mode
+    HDMI_AVI_YCRCB444_MODE = 2,  // YCrCb 4:4:4 mode
+    HDMI_AVI_FUTURE_MODE   = 3   // Future mode
+} avi_encoding_mode_t;
+
+// AVI Active Format Aspect Ratio
+typedef enum {
+    HDMI_AVI_AFAR_SAME   = 8,     // same as picture aspect ratio
+    HDMI_AVI_AFAR_4_3    = 9,     // 4:3 center
+    HDMI_AVI_AFAR_16_9   = 10,    // 16:9 center
+    HDMI_AVI_AFAR_14_9   = 11     // 14:9 center
+} avi_afar_info_t;
+
+// AVI Picture Aspect Ratio
+typedef enum {
+    HDMI_AVI_PAR_NODATA  = 0,      // No Data
+    HDMI_AVI_PAR_4_3     = 1,      // 4:3
+    HDMI_AVI_PAR_16_9    = 2,      // 16:9
+    HDMI_AVI_PAR_FUTURE  = 3       // Future
+} avi_par_info_t;
+
+// AVI Colorimetry Information
+typedef enum  {
+    HDMI_AVI_COLOR_NODATA = 0,    // No data
+    HDMI_AVI_COLOR_ITU601 = 1,    // SMPTE 170M, ITU601
+    HDMI_AVI_COLOR_ITU709 = 2,    // ITU709
+    HDMI_AVI_COLOR_FUTURE = 3     // Future
+} avi_color_info_t;
+
+// AVI Non-uniform Picture Scaling Info
+typedef enum {
+    HDMI_AVI_SCALING_NODATA      = 0,  // No scaling
+    HDMI_AVI_SCALING_HORIZONTAL  = 1,  // horizontal scaling
+    HDMI_AVI_SCALING_VERTICAL    = 2,  // vertical scaling
+    HDMI_AVI_SCALING_BOTH        = 3   // horizontal & vertical scaling
+} avi_scaling_infp_t;
+
+// AVI RGB Quantization Range
+typedef enum {
+    HDMI_AVI_RGBQUANT_DEFAULT = 0,  // Default value
+    HDMI_AVI_RGBQUANT_LIMITED = 1,  // Limited Range
+    HDMI_AVI_RGBQUANT_FULL    = 2,  // Full Range
+    HDMI_AVI_RGBQUANT_FUTURE  = 3   // Future use
+} avi_rgbquant_range_t;
+
+// AVI IT Content
+typedef enum {
+    HDMI_AVI_ITC_NODATA    = 0,  // No Data
+    HDMI_AVI_ITC_ITCONTENT = 1   //IT Content
+} avi_it_content_t;
+
+//
+// AVI InfoFrame definitions - end
+//
+
+//
+// SPD InfoFrame definitions - start
+//
+// SPD InfoFrame Data Byte 25, refer Table-17 in CEA-861b
+typedef enum {
+    HDMI_SPD_SRC_UNKNOWN     = 0x00,   // unknown
+    HDMI_SPD_SRC_DIGITAL_STB = 0x01,   // Digital STB
+    HDMI_SPD_SRC_DVD         = 0x02,   // DVD
+    HDMI_SPD_SRC_DVHS        = 0x03,   // D-VHS
+    HDMI_SPD_SRC_HDD_VIDEO   = 0x04,   // HDD Video
+    HDMI_SPD_SRC_DVC         = 0x05,   // DVC
+    HDMI_SPD_SRC_DSC         = 0x06,   // DSC
+    HDMI_SPD_SRC_VCD         = 0x07,   // Video CD
+    HDMI_SPD_SRC_GAME        = 0x08,   // Game
+    HDMI_SPD_SRC_PC          = 0x09    // PC General
+} spd_src_type_t;
+
+// SPD InfoFrame Vendor Name & Descriptor Length in bytes
+typedef enum {
+    HDMI_SPD_VNAME_LENGTH = 8,   // SPD Vendor Name Length in bytes
+    HDMI_SPD_VDESC_LENGTH = 16,  // SPD Vendor Descriptor Length in bytes
+} spd_namedesc_length_info_t;
+
+//
+// SPD InfoFrame definitions - end
+//
+
+//
+// InfoFrame Packet Header - generic
+//
+typedef struct _if_header {
+    uint8_t type;       // InfoFrame Type
+    uint8_t version;    // InfoFrame Version
+    uint8_t length;     // InfoFrame Length
+    uint8_t chksum;     // Checksum of the InfoFrame
+} if_header_t;
+
+//
+// AVI InfoFrame structure
+//
+typedef union _avi_if {
+    uint8_t avi_buf[HDMI_AVI_TOTAL_LENGTH];
+    #pragma pack(1)
+    struct
+    {
+        if_header_t avi_if_header;            // AVI header data
+        union
+        {
+            uint8_t byte1;
+            struct
+            {
+                uint8_t scan_info:2;     // scan information
+                uint8_t bar_info :2;     // bar information
+                uint8_t format  :1;     // active format information
+                uint8_t enc_mode :2;     // pixel encoding (RGB or YCrCb)
+                uint8_t b1rsvd  :1;     // reserved
+            };
+        };
+        union
+        {
+            uint8_t byte2;
+            struct
+            {
+                uint8_t afar        :4; // Active Format Aspect Ratio
+                uint8_t par         :2; // Picture Aspect Ratio
+                uint8_t colorimetry :2; // colorimetry
+            };
+        };
+        union
+        {
+            uint8_t byte3;
+            struct
+            {
+                uint8_t scaling_info    :2; // Scaling information
+                uint8_t rgbquant_range  :2; // RGB Quantization Range
+                uint8_t ext_colorimetry :3; //Extended Colorimetry
+                uint8_t it_content      :1; //IT Content
+            };
+        };
+        union
+        {
+            uint8_t byte4;
+            struct
+            {
+                uint8_t vic         :7; // Video Identification code (refer Table 13 in CEA-861b)
+                uint8_t b4rsvd      :1; // reserved
+            };
+        };
+        union
+        {
+            uint8_t byte5;
+            struct
+            {
+                uint8_t pr          :4; // pixel repetition (refer Table 15 in CEA-861b)
+                uint8_t b5rsvd      :4; // reserved
+            };
+        };
+        uint8_t byte6;                  // end of top bar(lower), set to "00"
+        uint8_t byte7;                  // end of top bar(upper), set to "00"
+        uint8_t byte8;                  // start of bottom bar(lower), set to "00"
+        uint8_t byte9;                  // start of bottom bar(upper), set to "00"
+        uint8_t byte10;                 // end of left bar(lower), set to "00"
+        uint8_t byte11;                 // end of left bar(upper), set to "00"
+        uint8_t byte12;                 // start of right bar(lower), set to "00"
+        uint8_t byte13;                 // start of right bar(upper), set to "00"
+    };
+    #pragma pack()
+} avi_if_t;
+
+//
+// SPD InfoFrame structure
+//
+typedef union _spd_if {
+    uint8_t spd_buf[HDMI_SPD_TOTAL_LENGTH];
+    #pragma pack(1)
+    struct
+    {
+        if_header_t spd_if_header; // SPD header data
+        uint8_t name[8];    // Vendor Name, 8 characters
+        uint8_t desc[16];   // Product Description, 16 characters
+        uint8_t sdi;        // Source Device Information
+    };
+    #pragma pack()
+} spd_if_t;
+
+//
+// Vendor Specific InfoFrame structure
+//
+typedef union _vs_if
+{
+    uint8_t vs_buf[HDMI_VS_MAX_TOTAL_LENGTH];
+    #pragma pack(1)
+    struct
+    {
+        if_header_t vs_if_header; // VS header data
+        uint8_t ieee_reg_id[3];   // 3-byte IEEE registration ID
+        uint8_t pay_load[24];        // Payload bytes
+    };
+    #pragma pack()
+} vs_if_t;
+
+//
+// AVI Infoframe structure for customization
+//
+
+typedef struct _avi_infoframe_custom {
+    //GUID        guid;                   // GUID
+    int32_t     command;              // Command
+    int32_t     flags;                // Flags
+    uint32_t    type_code;             // Type code of AVI Infoframe
+    uint32_t    version;              // Version of AVI Infoframe
+    uint32_t    length;               // Length of AVI Info Frame 
+    uint8_t     r3r0_valid;             // Reserved
+    uint8_t     it_content;             // IT Content
+    uint8_t     bar_info[8];           // Reserved
+    int32_t     active_format_aspect_ratio;// Reserved 
+    int32_t     non_uniform_scaling;     // Reserved 
+    int32_t     rgb_ycc_indicator;       // Reserved 
+    int32_t     ext_colorimetry;        // Reserved 
+    int32_t     pixel_factor;           // Reserved 
+    int32_t     bar_info_valid;           // Reserved 
+    int32_t     colorimetry;           // Reserved 
+    int32_t     aspect_ratio;           // Reserved 
+    int32_t     quant_range;            // Quantization Range
+    int32_t     video_code;             // Reserved 
+    int32_t     scan_info;              // Scan Information
+} avi_infoframe_custom_t;
+
+
+//
+// LinearPCM Consolidated Audio Data(CAD) structure
+//
+typedef union _lpcm_cad {
+    uint8_t value;
+    struct {
+        uint8_t maxch_cp_on       :3; // Max channels-1 supported with CP turned ON
+        uint8_t maxch_cp_off      :3; // Max channels-1 supported with CP turned OFF
+        uint8_t sp_20bit       :1; // 20-bit sample support
+        uint8_t sp_24bit       :1; // 24-bit sample support
+    };
+} lpcm_cad_t;
+
+//
+// CEA Short Audio Descriptor
+// 
+typedef struct _cea_861b_adb {
+#pragma pack(1)
+    union
+    {
+        uint8_t byte1;
+        struct
+        {
+            uint8_t   max_channels        :3; // Bits[0-2]
+            uint8_t   audio_format_code   :4;    // Bits[3-6], see AUDIO_FORMAT_CODES
+            uint8_t   b1reserved          :1;    // Bit[7] - reserved
+        };
+    };
+    union
+    {
+        uint8_t    byte2;
+        struct
+        {
+            uint8_t   sp_rate_32kHz             :1;    // Bit[0] sample rate = 32kHz
+            uint8_t   sp_rate_44kHz             :1;    // Bit[1] sample rate = 44kHz
+            uint8_t   sp_rate_48kHz             :1;    // Bit[2] sample rate = 48kHz
+            uint8_t   sp_rate_88kHz             :1;    // Bit[3] sample rate = 88kHz
+            uint8_t   sp_rate_96kHz             :1;    // Bit[4] sample rate = 96kHz
+            uint8_t   sp_rate_176kHz            :1;    // Bit[5] sample rate = 176kHz
+            uint8_t   sp_rate_192kHz            :1;    // Bit[6] sample rate = 192kHz
+            uint8_t   sp_rate_b2reserved        :1;    // Bit[7] - reserved
+        };
+    };
+    union
+    {
+        uint8_t   byte3;    // maximum bit rate divided by 8kHz
+        // following is the format of 3rd byte for uncompressed(LPCM) audio
+        struct
+        {
+            uint8_t    bit_rate_16bit                :1;    // Bit[0]
+            uint8_t    bit_rate_20bit                :1;    // Bit[1]
+            uint8_t    bit_rate_24bit                :1;    // Bit[2]
+            uint8_t    bit_rate_b3reserved        :5;    // Bits[3-7]
+        };
+    };
+#pragma pack()
+}cea_861b_adb_t; 
+
+//
+// Enhanced EDID Like Data aka EELD structure
+//
+typedef union _hdmi_eeld {
+    uint8_t eeld[HDMI_EELD_SIZE];
+    #pragma pack(1)
+    struct
+    {
+        // Byte[0] = ELD Version Number
+        union
+        {
+            uint8_t   byte0;          
+            struct
+            {
+                uint8_t reserved:3;      // Reserf
+                uint8_t eld_ver:5;      // ELD Version Number
+                                        //  00000b - reserved
+                                        //  00001b - first rev
+                                        //  00010b:11111b - reserved for future
+            };
+        };
+
+        // Byte[1] = Vendor Version Field
+               union
+               {
+                       uint8_t vendor_version;
+                       struct
+                       {
+                               uint8_t reserved1:3;
+                               uint8_t veld_ver:5; // Version number of the ELD extension.
+                                                   // This value is provisioned and unique to each vendor.
+                       };
+               };
+
+               // Byte[2] = Baseline Lenght field
+               uint8_t baseline_eld_length; // Length of the Baseline structure divided by Four.
+
+               // Byte [3] = Reserved for future use
+               uint8_t byte3;
+
+               // Starting of the BaseLine EELD structure
+               // Byte[4] = Monitor Name Length 
+               union
+               {
+                       uint8_t byte4;
+                       struct
+                       {
+                               uint8_t mnl:5;
+                               uint8_t cea_edid_rev_id:3;
+                       };
+               };
+
+               // Byte[5] = Capabilities
+               union
+               {
+                       uint8_t capabilities;
+                       struct
+                       {
+                               uint8_t hdcp:1; // Indicates HDCP support
+                               uint8_t ai_support:1;   // Inidcates AI support
+                               uint8_t connection_type:2; // Indicates Connection type 
+                                                         // 00 - HDMI
+                                                         // 01 - DP
+                                                         // 10 -11  Reserved for future connection types
+                               uint8_t sadc:4; // Indicates number of 3 bytes Short Audio Descriptors. 
+                       };
+               };
+
+               // Byte[6] = Audio Synch Delay
+               uint8_t audio_synch_delay; // Amount of time reported by the sink that the video trails audio in milliseconds.
+
+               // Byte[7] = Speaker Allocation Block
+               union
+               {
+                       uint8_t speaker_allocation_block;
+                       struct
+                       {
+                               uint8_t flr:1; // Front Left and Right channels
+                               uint8_t lfe:1; // Low Frequency Effect channel
+                               uint8_t fc:1;  // Center transmission channel
+                               uint8_t rlr:1; // Rear Left and Right channels
+                               uint8_t rc:1; // Rear Center channel
+                               uint8_t flrc:1; // Front left and Right of Center transmission channels
+                               uint8_t rlrc:1; // Rear left and Right of Center transmission channels
+                               uint8_t reserved3:1; // Reserved
+                       };
+               };
+
+               // Byte[8 - 15] - 8 Byte port identification value
+               uint8_t port_id_value[8];
+
+        // Byte[16 - 17] - 2 Byte Manufacturer ID
+        uint8_t manufacturer_id[2];
+
+        // Byte[18 - 19] - 2 Byte Product ID
+        uint8_t product_id[2];
+
+               // Byte [20-83] - 64 Bytes of BaseLine Data
+       uint8_t mn_sand_sads[64]; // This will include
+                                       // - ASCII string of Monitor name
+                                // - List of 3 byte SADs
+                                       // - Zero padding
+
+               // Vendor ELD Block should continue here!
+        // No Vendor ELD block defined as of now. 
+       };
+    #pragma pack()
+} hdmi_eeld_t;
+
+//
+// Data structure for misc HDMI data
+//
+typedef struct _misc_hdmi_data {
+    int32_t colorimetry   :4; // 
+    int32_t pr            :4; // pixel repetition value
+    int32_t reserved      :24;// reserved bits
+} misc_hdmi_data_t;
+
+//
+// Audio capability structure
+//
+typedef struct _device_audio_caps {
+    int32_t npl_design :8; // max number of audio packets device can
+                        // deliver per line
+    int32_t k0        :8; // The overhead(in pixels) per line requied
+                        // by device for setting up audio packets when
+                        // CP is disabled
+    int32_t k1        :8; // The overhead(in pixels) per line requied
+                        // by device for setting up audio packets when
+                        // CP is enabled
+    // Misc data
+    int32_t pr        :4; // Pixel Replication value
+    uint32_t is_hdcp   :1; // Driver, Device and Receiver support HDCP
+    uint32_t is_rptr   :1; // Receiver is HDCP repeater
+    int32_t reserved  :2; // reserved bits
+} device_audio_caps_t;
+
+typedef struct _audio_enable_flags {
+    uint32_t is_hdmi_display    :1; //1 if HDMI display, 0 if not HDMI display
+    uint32_t is_eld_valid       :1; //1 if ELD valid, 0 if ELD not valid
+    int32_t reserved1          :30;
+} audio_enable_flags_t;
+
+//
+// Data structure to exchange HDMI data through GetSetParameters interface
+//
+typedef struct _hdmi_parameters {
+    //GUID              Guid;
+    hdmi_command_t    command;
+    uint8_t           type;
+    uint8_t           size;
+    union {
+        hdmi_eeld_t    eeld_buffer;
+        avi_if_t       avi_infoframe;
+        spd_if_t       spd_infoframe;
+        vs_if_t        vs_infoframe;
+        union {
+            int32_t              gen_data;
+            device_audio_caps_t  audio_caps;
+            misc_hdmi_data_t     misc_data;
+            audio_enable_flags_t fl_audio_enable_flags;
+        };
+    };
+} hdmi_parameters_t;
+
+//
+// Audio format codes
+//
+typedef enum {
+    AUDIO_LPCM      = 0x0001,   // Linear PCM (eg. IEC60958)
+    AUDIO_AC3       = 0x0002,   // AC-3
+    AUDIO_MPEG1     = 0x0003,   // MPEG1 (Layers 1 & 2)
+    AUDIO_MP3       = 0x0004,   // MP3   (MPEG1 Layer 3)
+    AUDIO_MPEG2     = 0x0005,   // MPEG2 (multichannel)
+    AUDIO_AAC       = 0x0006,   // AAC
+    AUDIO_DTS       = 0x0007,   // DTS
+    AUDIO_ATRAC     = 0x0008,    // ATRAC
+    AUDIO_OBA       = 0x0009,   // One Bit Audio
+    AUDIO_DOLBY_DIGITAL = 0x000A, // Dolby Digital
+    AUDIO_DTS_HD    = 0x000B,    // DTS-HD
+    AUDIO_MAT       = 0x000C,    // MAT (MLP)
+    AUDIO_DST       = 0x000D,    // DST
+    AUDIO_WMA_PRO   = 0x000E     // WMA Pro
+} audio_format_codes_t;
+
+//
+// Data structure for byte #6 to 8 which has fixed definition
+//
+typedef struct _vsdb_char6_to_char8
+{
+    #pragma pack(1)
+
+    union
+    {
+        uint8_t byte1;
+        struct
+        {
+            uint8_t dvi_dual      :1; // Bit[0]
+            uint8_t b1reserved    :2; // Bits[1-2]
+            uint8_t dcy444        :1; // Bit[3] YCBCR 4:4:4 in Deep Color modes.
+            uint8_t dc30bit       :1; //Bit[4]
+            uint8_t dc36bit       :1; //Bit[5]
+            uint8_t dc48bit       :1; //Bit[6]
+            uint8_t supports_ai   :1; // Bit[7]
+        };
+        };
+
+    uint8_t max_tmds_clock;
+
+    union
+    {
+        uint8_t byte3;
+        struct
+        {
+            uint8_t b3reserved               :6; // Bit[0-5] reserved
+            uint8_t i_latency_field_present  :1;// Bit[6]
+            uint8_t latency_field_present    :1;// Bits[7]
+        };
+    };
+
+    #pragma pack()
+} vsdb_byte6_to_byte8_t;
+
+
+//
+// Gamut metadata structure
+//
+// Note : The data is written in big endian format
+#if 0
+// GUID for calling GBD interface
+// {EEE24BDF-6D30-40bf-9BA2-139F0FFFC797}
+#define DXVA_HDMI13_GBD_P0_GUID "{EEE24BDF-6D30-40BF-9BA2-139F0FFFC797}"
+DEFINE_GUID(GUID_DXVA_HDMI13_GBD_P0, 0xeee24bdf, 0x6d30, 0x40bf, 0x9b, 0xa2, 0x13, 0x9f, 0xf, 0xff, 0xc7, 0x97);
+#endif
+
+#define HDMI_GBD_PKT_TYPE 0x0A
+#define HDMI_GBD_P0_DATA_SIZE 27
+#define HDMI_MAX_VERTICES_DATA 25
+#define HDMI_MAX_FACET_DATA 25
+
+typedef enum {
+    VERTICES_AND_FACETS = 0,
+    RGB_MIN_MAX_RANGE    = 1
+} gbd_format_flag_t;
+
+typedef enum {
+    GBD_8BIT_PRECISION   = 0,
+    GBD_10BIT_PRECISION  = 1,
+    GBD_12BIT_PRECISION  = 2
+} gbd_color_precision_t;
+
+typedef enum {
+    RGB_BT709 = 0,
+    XVY_CC601 = 1,
+    XVY_CC709 = 2,
+    RESERVED_COLORSPACE
+} gbd_color_space_t;
+
+typedef enum {
+    MIN_RED_INDEX    = 0,
+    MAX_RED_INDEX    = 1,
+    MIN_GREEN_INDEX  = 2,
+    MAX_GREEN_INDEX  = 3,
+    MIN_BLUE_INDEX   = 4,
+    MAX_BLUE_INDEX   = 5,
+    MAX_RANGE_DATA_INDEX_LIMIT = 6
+} gbd_rgb_range_data_index_t;
+    
+//
+// App needs to feel the data in this structure
+//
+typedef struct _gbd_p0_hdmi_1_3 {
+    uint8_t enable;      // Enable/Disable GBD profile sending
+    gbd_format_flag_t     format_flag;         // uses GBD_FORMAT_FLAG_EN, this defines the gamut data format
+    gbd_color_precision_t color_precision;     // uses GBD_COLOR_PRECISION, this is the bit precision of GBD vertex and range data
+    gbd_color_space_t     color_space;         // uses GBD_COLOR_SPACE_EN, this defines the color space being represented
+
+    union 
+    {
+        // If bFormatFlag is 0
+        struct {
+            uint8_t facet_mode;     // spec supports 0 alone right now
+            uint16_t num_vertices;   // Number of vertices 
+            uint16_t num_facets;     // Number of faces
+            
+            // For 4 vertices of 12bits size is 18
+            // Max possible with 0 facets and 28 bytes of GBD is 28-5=23 bytes
+            uint16_t vertices_data[HDMI_MAX_VERTICES_DATA];   // Vertices data representation
+            uint16_t facets_data[HDMI_MAX_FACET_DATA];        // kept it as input data but to be defined based on future spec
+        } vertices_facets_data;
+
+
+        // If eFormatFlag is 1
+        struct {
+            uint16_t rgb_primary_data[MAX_RANGE_DATA_INDEX_LIMIT];
+        } rgb_range_data;
+    };    
+
+} gbd_p0_hdmi_1_3_t;
+
+#define HDMI_GBD_MAX_SEQ_NUM_INDEX 16
+
+// various GBD profiles
+typedef enum {
+    P0_PROFILE = 0,
+    P1_PROFILE = 1,
+    P2_PROFILE = 2,
+    P3_PROFILE = 3,
+    INVALID_PROFILE
+} gbd_profile_type_t;
+
+// various packet transmission options
+typedef enum {
+    INTERMEDIATE_PKT_IN_SEQ   = 0,
+    FIRST_PKT_IN_SEQ          = 1,
+    LAST_PKT_IN_SEQ           = 2,
+    ONLY_PKT_IN_SEQ           = 3
+} gbd_pkt_seq_t;
+
+//
+// Packet header defn as per HDMI spec
+//
+typedef struct _gamut_pkt_header {
+    uint8_t pkt_type; // Defines the pkt type
+    union{
+        uint8_t field_byte;
+        struct{
+            uint8_t affected_gamut_info  :4; // BIT 3:0
+            uint8_t gbd_profile          :3; // BIT 6:4 ; uses GBD_PROFILE_TYPE_EN
+            uint8_t next_field           :1; // BIT(7)
+        };
+    };
+
+    union{
+        uint8_t gbd_seq_info;
+        struct{
+            uint8_t current_gamut_info    :4; // BIT 3:0
+            uint8_t packet_seq            :2; // BIT 5:4 ; use GBD_PKT_SEQ_EN
+            uint8_t reserved2             :1; // BIT 6
+            uint8_t no_current_gbd        :1; // BIT 7
+        };
+    };
+} gamut_pkt_header_t;
+        
+//
+// Gamut structure contains data in following format
+// 
+typedef struct _gamut_metadata_struct {
+    #pragma pack(1)
+    gamut_pkt_header_t pkt_hdr;           // Gamut Metadata header data
+    union
+    {
+        uint8_t byte1;
+        struct
+        {
+            uint8_t gbd_color_space       :3; 
+            // Note: GBD buffer is formatted based upon the color precision
+            // 8 bit precision : 1 sign bit, 2 bits of integer, 5 bits of fraction
+            // 10 bit precision : 1 sign bit, 2 bits of integer, 7 bits of fraction
+            // 12 bit precision : 1 sign bit, 2 bits of integer, 9 bits of fraction
+            uint8_t gbd_color_precision   :2; 
+            uint8_t reserved3            :1; 
+            uint8_t facet_mode            :1;  // 0 - No facet info in GBD; 1 - Facet info in GBD
+            uint8_t format_flag          :1; // uses GBD_FORMAT_FLAG_EN
+        };
+    };
+
+    // For P0 profile below is the syntax in which data will be filled
+    // If Format is YUV
+    // char 2 : Higher 8 bits of number of vertices
+    // char 3 : Lower 8 bits of number of vertices
+    // char 4 to VSIZE+2 : Vertex data of size VSIZE, 
+    // where VSIZE = 3*number of vertices*GBD color precision/8 + 0.99999
+    // char VSIZE+3: Higher 8 bits of number of facets
+    // char VSIZE+4: Lower 8 bits of number of facets
+    // char VSIZE+5 to VSIZE+FSIZE+4 : Facet data
+    // where VSIZE = number of facet data
+    uint8_t   gbd_data[HDMI_GBD_P0_DATA_SIZE];         // data will be filled
+            
+    #pragma pack()
+} gamut_metadata_st_t;
+
+struct mid_intel_hdmi_priv {
+       u32 hdmib_reg;
+       u32 save_HDMIB;
+       bool has_hdmi_sink;
+       /* Should set this when detect hotplug */
+       bool hdmi_device_connected;
+       struct mdfld_hdmi_i2c *i2c_bus;
+       /* EELD packet holder*/
+       hdmi_eeld_t eeld;
+       u32 hdmi_eeld_size;
+       cea_861b_adb_t lpcm_sad;
+       bool is_hdcp_supported;
+       struct i2c_adapter *hdmi_i2c_adapter;   /* for control functions */
+       struct drm_device *dev;
+};
+
+struct hdmi_edid_info {
+       char monitor_name[HDMI_MONITOR_NAME_LENGTH];
+       char *edid_info;
+};
+
+#define HDMI_EDID_INFO(nm, info) \
+       .monitor_name = nm, .edid_info = info
+
+#define MSIC_IRQLVL1_STATUS 0x02
+  #define VREG_STATUS (1 << 5)
+#define MSIC_VRINT_STATUS 0x0d
+  #define HDMI_HPD_STATUS (1 << 3)
+  #define HDMI_OCP_STATUS (1 << 2)
+  #define VR_OCP_STATUS (1 << 1)
+  #define VR_OVP_STATUS (1 << 0)
+#define MSIC_VRINT_MASK 0x1c
+  #define HDMI_HPD_MASK (1 << 3)
+  #define HDMI_OCP_MASK (1 << 2)
+  #define VR_OCP_MASK (1 << 1)
+  #define VR_OVP_MASK (1 << 0)
+#define MSIC_IRQLVL1_MASK 0x21
+  #define VREG_MASK (1 << 5)
+#define MSIC_VCC330CNT 0xd3
+  #define VCC330_OFF 0x24
+  #define VCC330_ON 0x37
+#define MSIC_VHDMICNT 0xde
+  #define VHDMI_OFF 0x25
+  #define VHDMI_ON 0xa5
+#define MSIC_HDMI_STATUS 0x281
+  #define HPD_SIGNAL_STATUS (1 << 0)
+
+#endif //__IHDMI_H__
diff --git a/drivers/staging/mrst/drv/psb_intel_hdmi_edid.h b/drivers/staging/mrst/drv/psb_intel_hdmi_edid.h
new file mode 100644 (file)
index 0000000..952c080
--- /dev/null
@@ -0,0 +1,1057 @@
+/*
+ * Copyright Â© 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     
+ */
+/* chunfeng.zhao@intel.com
+  */
+#ifndef PSB_INTEL_HDMI_EDID_H
+#define PSB_INTEL_HDMI_EDID_H
+
+//#include "..\\..\\Common\\Platform.h"
+
+////////////////////////////////////////////
+//
+// Max number of EDID extensions possible
+//
+////////////////////////////////////////////
+#define MAX_EDID_EXTENSIONS                            254  //Max EDID blocks minus Block 0
+#define NUM_BASEEDID_STANDARD_TIMING   8
+#define MAX_BASEEDID_DTD_BLOCKS                        4
+
+#define MAX_VIC_DEFINED                                        128  
+
+// New Macros for supporting EDID 1.4
+
+// Macros for EDID Revision and Version
+#define EDID_VERSION_1 0x01
+#define EDID_REVISION_4 0x04
+
+// Macros for CVT and GTF related support in Monitor descriptor
+#define EDID14_CVT_TIMING_SUPPORTED 0x04
+#define EDID14_DEFAULT_GTF_SUPPORTED 0x00
+#define EDID14_SECONDARY_GTF_SUPPORTED 0x02
+
+// Macros for display device data block in CEA.
+#define EDID14_DISPLAY_DEVICE_DATA_TAG 0xFF
+#define EDID14_DISPLAY_DEVICE_DATA_CHILD_TAG 0x02
+#define EDID14_DISPLAY_DEVICE_DATA_LENGTH 0x20
+#define EDID14_DISPLAY_PORT_INTERFACE 0x09
+
+// Macros indicating digital interfaces supported by the display. 
+#define EDID14_DVI_SUPPORTED 0x01
+#define EDID14_DISPLAY_PORT_SUPPORTED 0x05
+#define EDID14_HDMI_A_SUPPORTED 0x02
+#define EDID14_HDMI_B_SUPPORTED 0x03
+
+#define EDID14_MAX_MONITOR_DESCRIPTORS 0x03
+
+// Macros related to EDID 1.4 Color Bit Depth support
+#define EDID14_COLOR_BIT_DEPTH_UNDEFINED         0x00
+#define EDID14_SIX_BITS_PER_PRIMARY_COLOR        0x06
+#define EDID14_EIGHT_BITS_PER_PRIMARY_COLOR      0x08
+#define EDID14_TEN_BITS_PER_PRIMARY_COLOR        0x0A
+#define EDID14_TWELVE_BITS_PER_PRIMARY_COLOR     0x0C
+#define EDID14_FOURTEEN_BITS_PER_PRIMARY_COLOR   0x0E
+#define EDID14_SIXTEEN_BITS_PER_PRIMARY_COLOR    0x10
+#define EDID14_INVALID_COLOR_BIT_DEPTH           0x07
+
+// Macro for showing Color Bit Depth support for existing displays
+#define EDID_EIGHT_BITS_PER_PRIMARY_COLOR        0x08
+
+// Macro for Established Timings III Block descriptor 
+#define EST_TIMINGS_III_BLOCK_TAG                0xF7
+#define EST_TIMINGS_III_BLOCK_DATA_LENGTH        0x06
+
+// Macro for indicating byte length
+#define BYTE_LENGTH                              0x08
+
+////////////////////////////////////////////
+//
+// Max number of EDID Blocks
+//
+////////////////////////////////////////////
+#define MAX_EDID_BLOCKS                                        255 //According to E-EDID Standard doc.
+#define EDID_BLOCK_SIZE                                        128
+
+// Macros for EDID Revision and Version for EDID 1.3
+#define EDID_VERSION_1_3 0x01
+#define EDID_REVISION_1_3 0x03
+
+////////////////////////////////////////////
+// Base EDID header
+////////////////////////////////////////////
+static const unsigned char BASEEDID_Header[8] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
+
+// Display Range Limits Offset Flags.
+// Applicable only from EDID 1.4 onwards
+typedef union _edid_range_limits_flags {
+       uint8_t ucRangeLimitOffsetFlags;        // Range Limits Offset Flags
+       struct {
+               uint8_t ucVerticalRateOffset   : 2; // Vertical Rate Offset
+               uint8_t ucHorizontalRateOffset : 2; // Horizontal Rate Offset
+               uint8_t ucReserved             : 4; // Reserved.
+               };
+} edid_range_limits_flags_t;
+
+////////////////////////////////////////////
+//
+//     18-byte DTD block
+//  Refer Table 3.16, 3.17 & 3.18 of 
+//  EDID spec
+//
+////////////////////////////////////////////
+typedef struct _edid_dtd_timing {
+#pragma pack(1)
+
+       int16_t wPixelClock;                                    // Pixel clock / 10000
+
+       uint8_t ucHA_low;                                               // Lower 8 bits of H. active pixels
+       uint8_t ucHBL_low;                                      // Lower 8 bits of H. blanking
+       union {
+               uint8_t ucHAHBL_high;
+               struct {
+                       uint8_t ucHBL_high : 4;         // Upper 4 bits of H. blanking
+                       uint8_t ucHA_high  : 4;         // Upper 4 bits of H. active pixels
+               };
+       };
+
+       uint8_t ucVA_low;                                               // Lower 8 bits of V. active lines
+       uint8_t ucVBL_low;                                      // Lower 8 bits of V. blanking
+       union {
+               uint8_t ucVAVBL_high;
+               struct {
+                       uint8_t ucVBL_high : 4;         // Upper 4 bits of V. blanking
+                       uint8_t ucVA_high  : 4;         // Upper 4 bits of V. active pixels
+               };
+       };
+
+       uint8_t ucHSO_low;                                      // Lower 8 bits of H. sync offset
+       uint8_t ucHSPW_low;                                     // Lower 8 bits of H. sync pulse width
+       union {
+               uint8_t ucVSOVSPW_low;
+               struct {
+                       uint8_t ucVSPW_low : 4;         // Lower 4 bits of V. sync pulse width
+                       uint8_t ucVSO_low  : 4;         // Lower 4 bits of V. sync offset
+               };
+       };
+       union {
+               uint8_t ucHSVS_high;
+               struct {
+                       uint8_t ucVSPW_high : 2;        // Upper 2 bits of V. sync pulse width
+                       uint8_t ucVSO_high  : 2;        // Upper 2 bits of V. sync offset
+                       uint8_t ucHSPW_high : 2;        // Upper 2 bits of H. sync pulse width
+                       uint8_t ucHSO_high  : 2;        // Upper 2 bits of H. sync offset
+               };
+       };
+
+       uint8_t ucHIS_low;                                      // Lower 8 bits of H. image size in mm
+       uint8_t ucVIS_low;                                      // Lower 8 bits of V. image size in mm
+       union {
+               uint8_t ucHISVIS_high;
+               struct {
+                       uint8_t ucVIS_high : 4;         // Upper 4 bits of V. image size
+                       uint8_t ucHIS_high : 4;         // Upper 4 bits of H. image size
+               };
+       };
+
+       uint8_t ucHBorder;                                      // H. border in pixels
+       uint8_t ucVBorder;                                      // V. border in pixels
+
+       union {
+               uint8_t ucFlags;                                        // Hsync & Vsync polarity, etc. flags
+               struct {
+                       uint8_t ucStereo1        : 1;   // Stereo definition with bit[6:5]
+                       uint8_t ucHSync_Pol  : 1;       // Hsync polarity (0: Neg, 1: Pos)
+                       uint8_t ucVSync_Pol  : 1;       // Vsync polarity (0: Neg, 1: Pos)
+                       uint8_t ucSync_Conf  : 2;       // Sync configuration
+                                                                               // 00 : Analog composite
+                                                                               // 01 : Bipolar analog composite
+                                                                               // 00 : Digital composite
+                                                                               // 00 : Digital separate
+                       uint8_t ucStereo2        : 2;   // Stereo definition
+                                                                               // 00 : Normal display, no stereo 
+                                                                               // xx : Stereo definition with bit0
+                       uint8_t ucInterlaced : 1;       // Interlaced / Non-interlaced
+                                                                               // 0 : Non-interlaced
+                                                                               // 1 : Interlaced
+               };
+       };
+
+#pragma pack()
+} edid_dtd_timing_t;
+
+
+////////////////////////////////////////////
+//
+//     Standard timing identification
+//  Refer Table 3.15 of EDID spec
+//
+////////////////////////////////////////////
+typedef union _edid_std_timing {
+       uint16_t  usStdTiming;
+
+       struct {
+#pragma pack(1)
+               uint8_t ucHActive;                              // (HActive/8) - 31;
+               struct {
+                       uint8_t ucRefreshRate : 6;      // Refresh Rate - 60
+                       uint8_t ucAspectRatio : 2;      // Aspect ratio (HActive/VActive)
+                                                                               // 00:  1:1 Aspect ratio
+                                                                               // 01:  4:3 Aspect ratio
+                                                                               // 10:  5:4 Aspect ratio
+                                                                               // 11: 16:9 Aspect ratio
+               };
+       };
+#pragma pack()
+
+} edid_std_timing_t;
+////////////////////////////////////////////////////////
+// Aspect Ratio def's as per Edid 1.3 Standard Timings
+////////////////////////////////////////////////////////
+#define EDID_STD_ASPECT_RATIO_16_10   0x0
+#define EDID_STD_ASPECT_RATIO_4_3     0x1
+#define EDID_STD_ASPECT_RATIO_5_4     0x2
+#define EDID_STD_ASPECT_RATIO_16_9    0x3
+
+
+////////////////////////////////////////////
+//
+//     Monitor range limits
+//
+////////////////////////////////////////////
+typedef struct _monitor_range_limits { 
+#pragma pack(1)
+
+       uint8_t ucMin_vert_rate;                        //Min Vertical Rate,in Hz
+       uint8_t ucMax_vert_rate;                        //Max Vertical Rate, in Hz
+       uint8_t ucMin_horz_rate;                        //Min Horizontal Rate, in Hz
+       uint8_t ucMax_horz_rate;                        //Max Horizontal Rate, in Hz
+       uint8_t ucMax_pixel_clock;              //Max Pixel Clock,Value/10 Mhz
+       uint8_t ucTiming_formula_support;       //00 - No Secondary Timing Formula Supported
+                                                                       //02 - Secondary GTF Curve Supported
+                                                                       //In EDID 1.4, this may indicate CVT support as well
+       //If timing_formula_support is 02
+       uint8_t ucReserved;                             //00h
+       uint8_t ucStart_freq;                           //Horizontal Freq, Value/2, KHz
+       uint8_t ucByte_C;                                       //C*2
+       uint8_t ucLSB_M;                                        //LSB of M Value
+       uint8_t ucMSB_M;                                        //MSB of M Value
+       uint8_t ucByte_K;                                       //K Value
+       uint8_t ucByte_J;                                       //J*2
+
+#pragma pack()
+} monitor_range_limits_t;
+
+////////////////////////////////////////////
+//
+// Color point
+//
+////////////////////////////////////////////
+typedef struct _color_point {
+#pragma pack(1)
+
+       uint8_t ucWhite_point_index_number_1;
+       uint8_t ucWhite_low_bits_1;
+       uint8_t ucWhite_x_1;
+       uint8_t ucWhite_y_1;
+       uint8_t ucWhite_gamma_1;
+       uint8_t ucWhite_point_index_number_2;
+       uint8_t ucWhite_low_bits_2;
+       uint8_t ucWhite_x_2;
+       uint8_t ucWhite_y_2;
+       uint8_t ucWhite_gamma_2;
+       uint8_t ucByte_15;
+       uint8_t ucByte_16_17[2];
+
+#pragma pack()
+} color_point_t;
+
+////////////////////////////////////////////
+//
+//     Monitor description descriptor
+//  Refer Table 3.19 & 3.20 of EDID spec
+//
+////////////////////////////////////////////
+#define BASEEDID_MONITORSN_MDDATATYPE                  0xFF
+#define BASEEDID_ASCIISTRING_MDDATATYPE                        0xFE
+#define BASEEDID_MONITORRANGELIMIT_MDDATATYPE  0xFD
+#define BASEEDID_MONITORNAME_MDDATATYPE                        0xFC
+#define BASEEDID_COLORPOINT_MDDATATYPE                 0xFB
+#define BASEEDID_STDTIMINGS_MDDATATYPE                 0xFA
+
+// Structure definition for Established Timings III monitor block
+typedef struct _est_timings_iii_block {
+#pragma pack(1)
+       // The first byte will show the VESA DMTS Standard Version. 
+       // The following six bytes will have the Timings Bit Mask.
+       // Right now only 6 bytes are used for this!!!
+       // Rest is reserved.
+       uint8_t ucVesaDMTVersion;       //Byte 0 indicating the VESA DMT Version.
+       uint8_t ucTimingBitMask[6];// Next 6 bytes indicating the Timing Bit Mask Bytes used in Est Timing III.
+       uint8_t bReserved[6];//Next 6 bytes are reserved
+#pragma pack()
+} est_timings_iii_block_t;
+
+typedef struct _monitor_descriptor {
+#pragma pack(1)
+
+       int16_t wFlag;                  // = 0000 when block is used as descriptor
+       uint8_t ucFlag0;                // Reserved
+
+       uint8_t ucDataTypeTag;
+
+       uint8_t ucFlag1;                // 00 for descriptor
+       
+       union {
+
+               // Monitor S/N (ucDataTypeTag = FF)
+               uint8_t ucMonitorSerialNumber[13];
+
+               // ASCII string (ucDataTypeTag = FE)
+               uint8_t ucASCIIString[13];
+
+               // Monitor range limit (ucDataTypeTag = FD)
+               monitor_range_limits_t MonitorRangeLimits;
+
+               // Monitor name (ucDataTypeTag = FC)
+               uint8_t ucMonitorName[13];
+
+               // Color point (ucDataTypeTag = FB)
+               color_point_t ColorPoint;
+
+               // ESTABLISHED TIMINGS III BLOCK = F7 (Added for EDID 1.4)
+               est_timings_iii_block_t stEstTimingsIIIBlock;
+
+               // Standard timings (ucDataTypeTag = FA)
+               struct {
+                       edid_std_timing_t ExtraStdTiming[6];
+                       uint8_t ucFixedValueOfA0;               // Should be 0xA0
+               };
+
+               // Manufacturer specific value (ucDataTypeTag = 0F-00)
+               uint8_t ucMfgSpecificData[13];
+       };
+
+#pragma pack()
+} monitor_descriptor_t;
+
+////////////////////////////////////////////
+//
+//     EDID PnP ID fields
+//
+////////////////////////////////////////////
+typedef union _baseedid_pnpid {
+       uint8_t         VendorProductID[10];    // Vendor / Product identification
+
+       struct {
+               uint8_t ManufacturerID[2];      // Bytes 8, 9: Manufacturer ID 
+               uint8_t ProductID[2];                   // Bytes 10, 11: Product ID
+               uint8_t SerialNumber[4];                // Bytes 12-15: Serial numbers
+               uint8_t WeekOfManufacture;      // Byte 16: Week of manufacture
+               uint8_t YearOfManufacture;      // Byte 17: Year of manufacture
+       };
+} baseedid_pnpid_t;
+
+//
+// Chromaticity structure
+// Table 3.12 of Base Block for details
+//
+typedef struct _baseedid_chromaticity_block {
+    union{
+            uint8_t RedGreenLowBits;           // Byte 1
+           struct{
+                uint8_t ucGreenYLowBits   : 2; // bit 1:0
+                uint8_t ucGreenXLowBits   : 2; // bit 3:2
+                uint8_t ucRedYLowBits     : 2; // bit 5:4
+                uint8_t ucRedXLowBits     : 2; // bit 7:6
+            };
+        };
+
+    union{
+            uint8_t ucBlueWhiteLowBits;       // Byte 2
+           struct{
+                uint8_t ucWhiteYLowBits   : 2; // bit 1:0
+                uint8_t ucWhiteXLowBits   : 2; // bit 3:2
+                uint8_t ucBlueYLowBits    : 2; // bit 5:4
+                uint8_t ucBlueXLowBits    : 2; // bit 7:6
+            };
+        };
+
+    uint8_t ucRedXUpperBits; // bit 9:2          Byte 3
+    uint8_t ucRedYUpperBits; // bit 9:2          Byte 4
+
+    uint8_t ucGreenXUpperBits; // bit 9:2        Byte 5
+    uint8_t ucGreenYUpperBits; // bit 9:2        Byte 6
+
+    uint8_t ucBlueXUpperBits; // bit 9:2         Byte 7
+    uint8_t ucBlueYUpperBits; // bit 9:2         Byte 8
+
+    uint8_t ucWhiteXUpperBits; // bit 9:2        Byte 9
+    uint8_t ucWhiteYUpperBits; // bit 9:2        Byte 10
+} baseedid_chromaticity_block_t;
+
+////////////////////////////////////////////
+//
+//     128-byte EDID 1.x block0 structure
+//
+////////////////////////////////////////////
+typedef struct _baseedid_1_x {
+#pragma pack(1)
+
+       //
+       // Header: 8 bytes (Table 3.3 of EDID spec)
+       char            Header[8];              // EDID1.x header "0 FFh FFh FFh FFh FFh FFh 0"
+       
+       //
+       // Vendor/Product ID: 10 bytes (Table 3.4, 3.5 & 3.6 of EDID spec)
+       //baseedid_pnpid_t;
+       union {
+               uint8_t         VendorProductID[10];    // Vendor / Product identification
+               struct {
+                       uint8_t ManufacturerID[2];      // Bytes 8, 9: Manufacturer ID 
+                       uint8_t ProductID[2];                   // Bytes 10, 11: Product ID
+                       uint8_t SerialNumber[4];                // Bytes 12-15: Serial numbers
+                       uint8_t WeekOfManufacture;      // Byte 16: Week of manufacture
+                       uint8_t YearOfManufacture;      // Byte 17: Year of manufacture
+               };
+       };
+       
+       //
+       // EDID structure Version/Revision: 2 bytes (Table 3.7 of EDID spec)
+       uint8_t         ucVersion;              // EDID version no.
+       uint8_t         ucRevision;             // EDID revision no.
+       
+       //
+       // Basic display parameters & features: 5 bytes (Table 3.8 of EDID spec)
+       union {
+               uint8_t ucVideoInput;   // Video input definition (Refer Table 3.9 of EDID spec)
+
+               struct {
+                       uint8_t ucSyncInput      : 4;   // Sync input supported (iff ucDigitInput = 0)
+                       uint8_t ucSetup          : 1;   // Display setup (iff ucDigitInput = 0)
+                       uint8_t ucSigLevStd      : 2;   // Signal level Standard (iff ucDigitInput = 0)
+
+                       uint8_t ucDigitInput : 1;       // 1: Digital input; 0: Analog input
+               };
+       };
+       
+       // Image size (Table 3.10 of EDID spec)
+       uint8_t         ucMaxHIS;               // Maximum H. image size in cm
+       uint8_t         ucMaxVIS;               // Maximum V. image size in cm
+       
+       // Gamma (display transfer characteristic)
+       uint8_t         ucGamma;                // Display gamma value  [= (gamma*100)-100]
+       
+       // Feature support (Table 3.11 of EDID spec)
+       union {
+               uint8_t ucDMPSFeature;  // DPMS feature support
+               
+               struct {
+                       uint8_t ucGTFSupport : 1;       // GTF timing support (1: Yes)
+                       uint8_t ucPTM            : 1;   // Preferred timing is 1st DTD (1: Yes) [Must if EDID >= 1.3]
+                       uint8_t ucColorSpace : 1;       // Use STD color space (1:Yes) [If set ColorChars should match sRGB values in EDID spec Appendix A]
+                       uint8_t ucDispType       : 2;   // Display type
+                                                                               // 00: Monochrome
+                                                                               // 01: R/G/B color display
+                                                                               // 10: Non R/G/B multicolor display
+                                                                               // 11: Undefined
+                       uint8_t ucActiveOff      : 1;   // Active off (Display consumes less power/blanks out when it receives an out of range timing)
+                       uint8_t ucSuspend        : 1;   // Suspend      (Refer VESA DPMS spec)
+                       uint8_t ucStandBy        : 1;   // Stand-by     (Refer VESA DPMS spec)
+               };
+       };
+
+       //
+       // Phosphor or Filter Chromaticity: 10 bytes
+       uint8_t         ColorChars[10]; // Color characteristics        (Refer Table 3.12 of EDID spec)
+
+       //
+       // Established timings: 3 bytes (Table 3.14 of EDID spec)
+       union {
+               uint8_t EstTiming1;
+               struct {
+                       uint8_t bSupports800x600_60     : 1;
+                       uint8_t bSupports800x600_56     : 1;
+                       uint8_t bSupports640x480_75     : 1;
+                       uint8_t bSupports640x480_72     : 1;
+                       uint8_t bSupports640x480_67     : 1;
+                       uint8_t bSupports640x480_60     : 1;
+                       uint8_t bSupports720x400_88     : 1;
+                       uint8_t bSupports720x400_70     : 1;
+               };
+       };
+       union {
+               uint8_t EstTiming2;
+               struct {
+                       uint8_t bSupports1280x1024_75   : 1;
+                       uint8_t bSupports1024x768_75    : 1;
+                       uint8_t bSupports1024x768_70    : 1;
+                       uint8_t bSupports1024x768_60    : 1;
+                       uint8_t bSupports1024x768_87i : 1;
+                       uint8_t bSupports832x624_75     : 1;
+                       uint8_t bSupports800x600_75     : 1;
+                       uint8_t bSupports800x600_72     : 1;
+               };
+       };
+       union {
+               uint8_t MfgTimings;
+               struct {
+                       uint8_t bMfgReservedTimings     : 7;
+                       uint8_t bSupports1152x870_75    : 1;
+               };
+       };
+
+       //
+       // Standard timings: 8 bytes (Table 3.15 of EDID spec)
+       edid_std_timing_t       StdTiming[NUM_BASEEDID_STANDARD_TIMING];        // 8 Standard timing support
+
+       //
+       // Detailed timing section - 72 bytes (4*18 bytes)
+       union {
+               edid_dtd_timing_t       DTD[MAX_BASEEDID_DTD_BLOCKS];                   // Four DTD data blocks
+
+               monitor_descriptor_t MonitorInfo[MAX_BASEEDID_DTD_BLOCKS];
+       };
+       
+       uint8_t         ucNumExtBlocks; // Number of extension EDID blocks
+       uint8_t         ucChecksum;             // Checksum of the EDID block
+
+#pragma pack()
+} baseedid_1_x_t;
+
+////////////////////////////////////////////
+//
+//     128-byte EDID 1.4 block0 structure
+//  EDID 1.4 block0 structure is different from 1.3 block0
+//  Thats why this new structure has been added 
+//  Changes are commented in the structure itself
+//
+////////////////////////////////////////////
+typedef struct _baseedid_1_4 {
+#pragma pack(1)
+
+       //
+       // Header: 8 bytes (Table 3.3 of EDID spec)
+       char            Header[8];              // EDID1.x header "0 FFh FFh FFh FFh FFh FFh 0"
+       
+       //
+       // Vendor/Product ID: 10 bytes (Table 3.4, 3.5 & 3.6 of EDID spec)
+       union {
+               uint8_t         VendorProductID[10];    // Vendor / Product identification
+               struct {
+                       uint8_t ManufacturerID[2];      // Bytes 8, 9: Manufacturer ID 
+                       uint8_t ProductID[2];                   // Bytes 10, 11: Product ID
+                       uint8_t SerialNumber[4];                // Bytes 12-15: Serial numbers
+                       uint8_t WeekOfManufacture;      // Byte 16: Week of manufacture
+                       uint8_t YearOfManufacture;      // Byte 17: Year of manufacture
+               };
+       };
+       
+       //
+       // EDID structure Version/Revision: 2 bytes (Table 3.7 of EDID spec)
+       uint8_t         ucVersion;              // EDID version no.
+       uint8_t         ucRevision;             // EDID revision no.
+       
+       //
+       // Basic display parameters & features: 5 bytes (Table 3.8 of EDID spec)
+       union {
+               uint8_t ucVideoInput;   // Video input definition (Refer Table 3.9 of EDID spec)
+
+               struct {
+                       uint8_t ucSyncInput      : 4;   // Sync input supported (iff ucDigitInput = 0)
+                       uint8_t ucSetup          : 1;   // Display setup (iff ucDigitInput = 0)
+                       uint8_t ucSigLevStd      : 2;   // Signal level Standard (iff ucDigitInput = 0)
+
+                       uint8_t ucDigitInput : 1;       // 1: Digital input; 0: Analog input
+               };
+               // This structure has been introduced to reflect the changes in EDID 1.4 spec
+               // This sturcture shows new meaning of VIDEO INPUT DEFINITION when input is digital 
+               struct {
+                       uint8_t ucDigitalVideoInterface : 4;    // Digital Video Interface Standard Supported.
+                       uint8_t ucColorBitDepth                 : 3;    // Color Bit Depth. 
+                                                                                                       // 0 0 0 -- Color Bit Depth is undefined
+                                                                                                       // 0 0 1 -- 6 Bits per Primary Color
+                                                                                                       // 0 1 0 -- 8 Bits per Primary Color
+                                                                                                       // 0 1 1 -- 10 Bits per Primary Color
+                                                                                                       // 1 0 0 -- 12 Bits per Primary Color
+                                                                                                       // 1 0 1 -- 14 Bits per Primary Color
+                                                                                                       // 1 1 0 -- 16 Bits per Primary Color
+                                                                                                       // 1 1 1 -- Reserved (Do Not Use)
+                       uint8_t bIsDigitalVideoSignalInterface  : 1; // Bit 7
+               };
+       };
+       
+       // As per the EDID spec 1.4, the following two fields can be aspect ratios as well. 
+       union {
+                       uint8_t ucMaxHIS; // Maximum H. image size in cm 
+                       uint8_t ucARLandscape; // Landscape Aspect raio as per EDID 1.4 spec
+       };
+       union {
+                       uint8_t ucMaxVIS; // Maximum V. image size in cm 
+                       uint8_t ucARPortrait; // Portrait Aspect raio as per EDID 1.4 spec
+       };
+       
+       // Gamma (display transfer characteristic)
+       uint8_t         ucGamma;                // Display gamma value  [= (gamma*100)-100]
+       
+       // Feature support (Table 3.11 of EDID spec)
+       union {
+               uint8_t ucDMPSFeature;  // DPMS feature support
+               
+               struct {
+                       uint8_t ucContinuousDisplay : 1;        // Display is continuous or non-continuous (1: Yes)
+                       uint8_t ucPTM            : 1;   // Preferred timing mode indicates native pixel format and native RR. 
+                       uint8_t ucColorSpace : 1;       // Use STD color space (1:Yes) [If set ColorChars should match sRGB values in EDID spec Appendix A]
+                       uint8_t ucDispType       : 2;   // Display type
+                                                                               // 00: Monochrome
+                                                                               // 01: R/G/B color display
+                                                                               // 10: Non R/G/B multicolor display
+                                                                               // 11: Undefined
+                       uint8_t ucActiveOff      : 1;   // Active off (Display consumes less power/blanks out when it receives an out of range timing)
+                       uint8_t ucSuspend        : 1;   // Suspend      (Refer VESA DPMS spec)
+                       uint8_t ucStandBy        : 1;   // Stand-by     (Refer VESA DPMS spec)
+               };
+
+               struct {
+                       uint8_t bReserved0 : 1;
+                       uint8_t bReserved1 : 1;
+                       uint8_t bReserved2 : 1;
+                       uint8_t ucColorEncodingFormat    : 2;   // Supported Color Encoding Format if Video Input is digital
+                                                                                                       // 00: RGB 4:4:4
+                                                                                                       // 01: RGB 4:4:4 & YCrCb 4:4:4
+                                                                                                       // 10: RGB 4:4:4 & YCrCb 4:2:2
+                                                                                                       // 11: RGB 4:4:4 & YCrCb 4:4:4 & YCrCb 4:2:2
+                       uint8_t bReserved3 : 1;
+                       uint8_t bReserved4 : 1;
+                       uint8_t bReserved5 : 1;
+               };
+       };
+
+       //
+       // Phosphor or Filter Chromaticity: 10 bytes
+       uint8_t         ColorChars[10]; // Color characteristics        (Refer Table 3.12 of EDID spec)
+
+       //
+       // Established timings: 3 bytes (Table 3.14 of EDID spec)
+       union {
+               uint8_t EstTiming1;
+               struct {
+                       uint8_t bSupports800x600_60     : 1;
+                       uint8_t bSupports800x600_56     : 1;
+                       uint8_t bSupports640x480_75     : 1;
+                       uint8_t bSupports640x480_72     : 1;
+                       uint8_t bSupports640x480_67     : 1;
+                       uint8_t bSupports640x480_60     : 1;
+                       uint8_t bSupports720x400_88     : 1;
+                       uint8_t bSupports720x400_70     : 1;
+               };
+       };
+       union {
+               uint8_t EstTiming2;
+               struct {
+                       uint8_t bSupports1280x1024_75   : 1;
+                       uint8_t bSupports1024x768_75    : 1;
+                       uint8_t bSupports1024x768_70    : 1;
+                       uint8_t bSupports1024x768_60    : 1;
+                       uint8_t bSupports1024x768_87i : 1;
+                       uint8_t bSupports832x624_75     : 1;
+                       uint8_t bSupports800x600_75     : 1;
+                       uint8_t bSupports800x600_72     : 1;
+               };
+       };
+       union {
+               uint8_t MfgTimings;
+               struct {
+                       uint8_t bMfgReservedTimings     : 7;
+                       uint8_t bSupports1152x870_75    : 1;
+               };
+       };
+
+       //
+       // Standard timings: 8 bytes (Table 3.15 of EDID spec)
+       edid_std_timing_t StdTiming[NUM_BASEEDID_STANDARD_TIMING];      // 8 Standard timing support
+
+       // Detailed timing section - 72 bytes (4*18 bytes)
+       // As per the new spec 1.4, the first Detailed Timing Section should contain the PREFERED TIMING BLOCK
+       edid_dtd_timing_t PreferedTimingMode;
+       // The rest 54 bytes of the Detailed Timing Section. 
+       union {
+               edid_dtd_timing_t DTD[MAX_BASEEDID_DTD_BLOCKS - 1];                     // Three DTD data blocks
+
+               monitor_descriptor_t MonitorInfo[MAX_BASEEDID_DTD_BLOCKS - 1]; // Three Monitor Descriptor blocks
+       };
+       
+       uint8_t         ucNumExtBlocks; // Number of extension EDID blocks
+       uint8_t         ucChecksum;             // Checksum of the EDID block
+
+#pragma pack()
+} baseedid_1_4_t;
+
+
+//*****************************************************
+//*****************************************************
+//
+// DATA STRUCTURES AND DEFINITIONS FOR CE-EXTENSION
+//
+//*****************************************************
+//*****************************************************
+
+/////////////////////////////////
+//
+//CE - Extension Block Structure
+//
+/////////////////////////////////
+typedef struct _ce_edid {
+       uint8_t ucTag;
+       uint8_t ucRevision;
+       uint8_t ucDTDOffset;
+       uint8_t ucCapabilty;
+       uint8_t data[123];
+       uint8_t   ucCheckSum;   
+} ce_edid_t;
+
+////////////////////////////////////////////
+//
+//CE - Video Capability Data block structure
+//
+////////////////////////////////////////////
+typedef union _video_cap_data_block {
+    uint8_t ucValue;
+    struct
+    {
+        uint8_t ucCEScanBehavior        :2; // Indicates scan behavior of CE mode
+        uint8_t ucITScanBehavior        :2; // Indicates scan behavior of IT mode
+        uint8_t ucPTScanBehavior        :2; // Indicates scan behavior of Preferred mode
+        uint8_t ucQuantRangeSelectable  :1; // Indicates if RGB Quantization Range can be overridden
+        uint8_t ucReserved              :1;
+    };
+} video_cap_data_block_t;
+
+////////////////////////////////////////////
+//
+//CEA Extn Block Byte3 structure
+//
+////////////////////////////////////////////
+typedef union _cea_ext_capability {
+    uint8_t ucValue;
+    struct
+    {
+        uint8_t ucTotalNativeDTDs     :4; // Total number of DTDs in extension block
+        uint8_t ucSupportsYCBCR422    :1; // Indicates support for YCBCR 4:2:2
+        uint8_t ucSupportsYCBCR444    :1; // Indicates support for YCBCR 4:4:4
+        uint8_t ucSupportsBasicAudio  :1; // Indicates support for Basic audio
+        uint8_t ucUnderscansITFormats :1; // Indicates underscan behavior of IT formats
+    };
+} cea_ext_capability_t;
+
+////////////////////////////////////////////
+//
+//CE - Video Capability Data block structure
+//
+////////////////////////////////////////////
+typedef enum {
+    FORMAT_NOT_SUPPORTED        = 0, // Format is not supported
+    ALWAYS_OVERSCANNED          = 1, // Format is always overscanned
+    ALWAYS_UNDERSCANNED         = 2, // Format is always underscanned
+    SUPPORTS_OVER_AND_UNDERSCAN = 3  // Sink supports both overscan and underscan
+} cea_scan_behavior_t;
+
+
+/////////////////////////////////
+//
+// #defines required for CE Etxn
+//
+/////////////////////////////////
+#define CEA_EXT_TAG 0x02
+#define CEA_EXT_SUPPORTED_VERSION 0x03
+#define CEA_EXT_861_REVISION 0x01
+
+#define CEA_USE_EXTENDED_TAG   0x7
+
+#define CEA_AUDIO_DATABLOCK         0x1
+#define CEA_VIDEO_DATABLOCK         0x2
+#define CEA_VENDOR_DATABLOCK        0x3
+#define CEA_SPEAKER_DATABLOCK       0x4
+#define CEA_VIDEO_CAP_DATABLOCK     0x0
+
+#define CEA_DATABLOCK_TAG_MASK                  0xE0
+#define CEA_DATABLOCK_LENGTH_MASK               0x1F
+#define CEA_SHORT_VIDEO_DESCRIPTOR_CODE_MASK    0x7F
+#define CEA_NATIVE_FORMAT_BIT_MASK              0x80
+
+#define CEA_HDMI_IEEE_REG_ID    0x00000C03
+#define CEA_EDID_HEADER_SZIE    0x04
+
+// Extended Data block type
+// This bit definitions are as per CE 861-D spec
+#define CEA_COLORIMETRY_DATABLOCK   0x5
+    #define CE_COLORIMETRY_MD0_MASK BIT(0)     
+    #define CE_COLORIMETRY_MD1_MASK BIT(1)
+    #define CE_COLORIMETRY_MD2_MASK BIT(3)
+#if 0
+//==================================================================================
+//==================================================================================
+//     DATA Structure definitions for VTB parsing.....
+//  Reference VESA Documents are VTB Extension(Release A) & CVT standard version 1.1
+//===================================================================================
+//     #defines for VTB-EXT
+//===================================================================================
+
+#define VTB_EXT_TAG    0x10
+#define        VTB_EXT_SUPPORTED_VERSION 0x03
+
+#define        VTB_MAX_DTD_TIMINGS                      6
+#define        VTB_MAX_CVT_TIMINGS                     40
+#define        VTB_MAX_STANDARD_TIMINGS        61
+
+#define VTB_DTD_OFFSET         5
+#define VTB_DTD_SIZE           18
+#define        VTB_CVT_SIZE            3
+#define VTB_ST_SIZE                    2
+
+// This struct is for VTB Extension block.
+typedef struct _VTB_EXT
+{
+       uint8_t ucTag;
+       uint8_t ucVersion;
+       uint8_t ulNumDTD;
+       uint8_t ulNumCVT;
+       uint8_t ulNumST;
+       uint8_t DATA[122];
+       uint8_t ucChecksum;
+}VTB_EXT, *PVTB_EXT;
+
+// Following struct is for CVT descriptor (Version 1.1)
+typedef struct _VTB_CVT_TIMING 
+{
+#pragma pack(1)        
+
+       uint8_t ucVA_low;               // Lower 8 bits of Vertical size. This Vsize = (vertical active lines/2)-1. 
+                                                       //      Range for VA lines is 2 to 8192. CVT supprts only an even no. of active lines per frame.
+       
+       union {                                 
+               uint8_t ucVA_high_AR;
+               struct {
+               
+                       uint8_t ucReserved00    :2;             //Bits 1-0 are reserved and set to 00h
+                       uint8_t ucAspectRatio   :2;             //      Aspect Ratio specifier bits.
+                                                                                       // 00:   4:3 Aspect ratio
+                                                                                       // 01:  16:9 Aspect ratio
+                                                                                       // 10:  16:10 Aspect ratio
+                                                                                       // 11: Undefined (Reserved)
+                       
+                       
+                       uint8_t ucVA_high       :4;                     //      Upper 4 bits of Vertical Size.
+               };
+       };
+
+       union {
+               uint8_t ucRefresh_Rate_Bits;
+               struct  {
+                       
+                       uint8_t ucRR_60Hz_RB    :1;             // When set, indicates 60Hz support with Reduced Blanking.
+                       uint8_t ucRR_85Hz       :1;                     //                              ||         85Hz                         ||                                                                                              .
+                       uint8_t ucRR_75Hz       :1;                     //                              ||         75Hz                         ||                                                                                              .
+                       uint8_t ucRR_60Hz       :1;                     //                              ||         60Hz                         ||                                                                                              .
+                       uint8_t ucRR_50Hz       :1;                     // When set, indicates 50Hz Refrash Rate with CRT Blanking supports specified pixel format.
+                       uint8_t ucPreferredRefresh_Rate :2;             // Preferred Refresh Rate specifier bits.
+                                                                                       // 00:  50 Hz
+                                                                                       // 01:  60 Hz (this means either CRT blanking or Reduced Blanking whichever is supported. 
+                                                                                       //                              If both are supported, then RB is preferred.)
+                                                                                       // 10:  75 Hz
+                                                                                       // 11:  85 Hz   
+                       
+                       uint8_t ucReserved0     :1;                     // This bit is reserved and set to '0'.
+                       
+               };
+       };
+#pragma        pack()
+} VTB_CVT_TIMING, *PVTB_CVT_TIMING;
+
+
+// This struct is for storing extracted Info from CVT descriptor....
+// This is defined by author.....not based on CVT specs.
+typedef struct _CVT_INFO               
+{
+       ULONG ulYRes;
+       ULONG ulXRes;
+       ULONG ulRRate[5];                       //As max 5 Refresh Rates can be supported.
+       BOOLEAN bRed_Blank_Req[5];
+       BOOLEAN bPreferred_RR[5];   //To set flag for Preffered RR
+       ULONG ulNumRates;                       //Number of Refresh rates Supported. (Max. 5)
+} CVT_INFO, *PCVT_INFO;
+#endif 
+// This structure is for stroing the Display device Data retreived from CEA block
+// This is defined as per the Display Device Data Block standard.
+typedef struct _display_device_data {
+#pragma pack (1)
+       union 
+       {
+               uint8_t ucTagAndLength; // Data Block Tag and Block Length. should be 0xFF
+               struct
+               {
+                       uint8_t ucLength : 5;
+                       uint8_t ucTag : 3;
+               };
+       };
+       uint8_t ucChildTag; // Child tag required as per CEA spec  should be 0x02
+       union
+       {
+               uint8_t ucInterfaceType;
+               struct
+               {
+                       uint8_t ucNumOfChannels : 4;// Number of channels supported
+                       uint8_t ucInterfaceCode : 4;// Interface code 
+               };
+       };
+       union
+       {
+               uint8_t ucVerAndRel;
+               struct
+               {
+                       uint8_t ucRelease : 4;// Release 
+                       uint8_t ucVersion : 4;// Version.
+               };
+       };
+       uint8_t ucContentProtectionSuppFlag;// Flag indicating support for content protection. 
+       union
+       {
+               uint16_t usClockFrequency;// Clock Frequency
+               struct
+               {
+                       uint16_t usMinClockFrequency : 6; // First 6 bits indicates Min frequency
+                       uint16_t usMaxClockFrequency : 10;// Next 10 bits indicates Max frequency
+               };
+       };
+       union
+       {
+               uint8_t ucNativePixelFormat[4];// Pixel Format
+               struct
+               {
+                       uint8_t ucHorizontalPixelCntLower;// Lower byte value of the Horizontal pixel count
+                       uint8_t ucHorizontalPixelCntUpper;// Upper byte value of the Horizontal pixel count
+                       uint8_t ucVerticalPixelCntLower;//  Lower byte value of the vertical pixel count
+                       uint8_t ucVerticalPixelCntUpper; // Upper byte value of the vertical pixel count
+               };
+       };
+       uint8_t ucAspectRatio;// Byte indicating Aspect ratio. 
+       union 
+       {
+               uint8_t ucOrientationAndRotation;
+               struct
+               {
+                       uint8_t ucScanDirection : 2;// Scan direction.
+                       uint8_t ucZeroPixelLocation : 2;// Zero Pixel Location.
+                       uint8_t ucRotationCapability : 2;// Indicates rotation capability
+                       uint8_t ucDefaultOrientation : 2;// Default Orientation.
+               };
+       };
+       uint8_t ucSubPixelInfo;// Sub-Pixle Information.
+       uint8_t ucHorizontalPitch;// Horizontal Pitch
+       uint8_t ucVerticalPitch;// Vertical Pitch
+       union
+       {
+               uint8_t ucMiscDisplayCapabilities;
+               struct
+               {
+                       uint8_t bReserved : 3;
+                       uint8_t ucDeinterlacing : 1;// indicates deinterlacing support
+                       uint8_t ucOverdriverNotRecommended : 1;
+                       uint8_t ucDirectDrive : 1;// indicates DirectDrive support
+                       uint8_t ucDithering : 2;// indicates Dithering support.
+               };
+       };
+       union
+       {
+               uint8_t ucAudioFlags;// Flags indicating Audio details
+               struct
+               {
+                       uint8_t bReserved1 : 4;
+                       uint8_t ucAudioInputOverride : 1;// Indicates Audio Input Override
+                       uint8_t ucSeparateAudioInputs : 1;// Indicates Separate Audio Inputs
+                       uint8_t ucAudioInputOnVideoInterface : 1;// Shows whether Audio input is through the video interface.
+               };
+       };
+       union
+       {
+               uint8_t ucAudioDelayFlags; // Audio Delay Flags
+               struct
+               {
+                       uint8_t ucAudioDelay : 7;// Absolute offset between the audio and video signals.
+                       uint8_t ucAudioSign : 1;// Indicates positive or negative delay.
+               };
+       };
+       union
+       {
+               uint8_t ucFrameRateAndModeConversion;
+               struct
+               {
+                       uint8_t ucFrameRateRange : 6;//Device Frame rate Range
+                       uint8_t ucFrameRateConversion : 2;//00 ï¿½ No dedicated rate conversion hardware is provided;
+                                                                                       //01 ï¿½ The display provides a single frame buffer
+                                                                                       //10 ï¿½ The display provides double-buffering
+                                                                                       //11- The display provides frame-rate conversion involving interframe interpolation
+               };
+       };
+       uint8_t ucDeviceNativeRate;// Device Native Frame rate
+       union
+       {
+               uint8_t ucColorBitDepth;// Color bit depth
+               struct
+               {
+                       uint8_t ucDisplayDeviceColBitDepth : 4; // Color bit depth of the display device
+                       uint8_t ucInterfaceColBitDepth : 4;// color bit depth supported by the interface.h
+               };
+       };
+       uint8_t ucAddPrimaryChromaticities[8];// Additional Primary Chromaticities.
+       union
+       {
+               uint8_t ucResponseTimeFlags;
+               struct
+               {
+                       uint8_t ucResponseTime : 7;// Time for transition.
+                       uint8_t ucBlackToWhite : 1;// if 1, then transition from black to white
+                                                                       // if 0, then transition from white to black
+               };
+       };
+       union
+       {
+               uint8_t ucOverscanInformation;
+               struct
+               {
+                       uint8_t ucVerticalPercentage : 4;// Percentage of Overscan in vertical direction.
+                       uint8_t ucHorizontalPercentage : 4;// Percentage of Overscan in horizontal direction.
+               };
+       };
+#pragma pack()
+} display_device_data_t;
+
+//=========================================================================
+//=========================================================================
+// #defines for Block Map Ext.
+//=========================================================================
+//=========================================================================
+#define BLOCK_MAP_EXT_TAG 0xF0
+
+#endif // EDIDSTRUCTS_H
diff --git a/drivers/staging/mrst/drv/psb_intel_hdmi_i2c.c b/drivers/staging/mrst/drv/psb_intel_hdmi_i2c.c
new file mode 100644 (file)
index 0000000..2312149
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright Â© 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     
+ */
+/* chunfeng.zhao@intel.com
+  */
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#if 0 /* FIXME_JLIU7 HDMI */
+#include "psb_intel_hdmi_i2c.h" 
+
+#define MDFLD_HDMI_I2C_ADAPTER_ID 3
+
+static int hdmi_i2c_open(struct i2c_client *c, void *data)
+{
+       /*Do nothing for now, may need to add sync code? */
+       return 0;
+}
+
+static int hdmi_i2c_close(struct i2c_client *c, void *data)
+{
+       /*Do nothing for now, may need to add sync code? */
+       return 0;
+}
+
+static char hdmi_i2c_read_byte_data(struct i2c_client *c, unsigned char adr)
+{
+       return i2c_smbus_read_byte_data(c, adr);
+}
+
+static int hdmi_i2c_write_byte_data(struct i2c_client *c, unsigned char adr, unsigned char data)
+{
+       return i2c_smbus_write_byte_data(c, adr, data);
+}
+
+static int hdmi_i2c_read_data(struct i2c_adapter * adapter,  unsigned char adr, unsigned char * data, int size)
+{
+        struct i2c_msg msg = {
+                .addr = adr,.flags = I2C_M_RD,.buf = data,.len = size
+        };
+        return i2c_transfer(adapter, &msg, 1);
+}
+
+static int hdmi_i2c_write_data(struct i2c_adapter * adapter, unsigned char adr, unsigned char *data, int size)
+{
+        struct i2c_msg msg = {
+                .addr = adr,.flags = 0,.buf = data,.len = size
+        };
+        return i2c_transfer(adapter, &msg, 1);
+}
+
+static struct i2c_adapter * hdmi_i2c_get_adapter(struct i2c_client *c)
+{
+        /* For HDMI if not plugged in, then i2c core may not create the client driver */
+        /* Should use the adapter directly */
+        if(c)
+          return c->adapter;
+       else
+          return i2c_get_adapter(MDFLD_HDMI_I2C_ADAPTER_ID);
+} 
+
+static struct mdfld_hdmi_i2c hdmi_i2c_bus = {
+       .open = hdmi_i2c_open,
+       .close = hdmi_i2c_close,
+       .read_byte_data = hdmi_i2c_read_byte_data,
+       .write_byte_data = hdmi_i2c_write_byte_data,
+       .read_data = hdmi_i2c_read_data,
+       .write_data = hdmi_i2c_write_data,
+       .get_adapter = hdmi_i2c_get_adapter,
+};
+
+struct mdfld_hdmi_i2c * hdmi_i2c_init()
+{
+       return &hdmi_i2c_bus;
+}
+
+/*
+ *  * i2c addresses to scan 
+ *  0x28 is from 0x50 >> 1 to remove first bit for ddc address 
+ *  0x39 is from 0x73 >> 1 for HDCP address
+ *   */
+static unsigned short normal_i2c[] = {0x28, 0x39, I2C_CLIENT_END};
+I2C_CLIENT_INSMOD;
+
+/* Each client has this additional data */
+struct mdfld_hdmi_i2c_data {
+       struct semaphore data_lock;
+       int data;
+};
+
+static const struct i2c_device_id mdfld_hdmi_id[] = {
+       {"mdfld_hdmi", 0},
+       {}
+};
+
+static int mdfld_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       return 0;
+}
+
+/* This function is called by i2c_detect */
+static int mdfld_detect(struct i2c_client *client, int kind,
+                        struct i2c_board_info *info)
+{
+       struct i2c_adapter *adapter = client->adapter;
+       struct mdfld_hdmi_i2c_data *data = NULL;
+       int err = 0;
+
+       /* HDMI i2c is i2c3 with id = 3 */
+       if (adapter->id !=3) {
+               err = -ENODEV;
+               goto error;
+       }
+               
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               err = -ENODEV;
+               goto error;
+       }
+
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               err = -ENOMEM;
+               goto error;
+       }
+                       
+       memset(data, 0x00, sizeof(*data));
+       
+       i2c_set_clientdata(client, data);
+       
+       if (client->addr == 0xA0)
+               hdmi_i2c_bus.ddc_client = client;
+       else    
+               hdmi_i2c_bus.hdcp_client = client;              
+
+       return 0;
+
+error:
+       if(data != NULL) kfree(data);
+       return err;
+}
+
+static int mdfld_remove(struct i2c_client *client)
+{
+       struct mdfld_hdmi_i2c_data *data = i2c_get_clientdata(client);
+       kfree(data);
+       return 0;
+}
+
+/* This is the driver that will be inserted */
+static struct i2c_driver mdfld_hdmi_i2c_driver = {
+       .driver = {
+               .name           = "mdfld_hdmi",
+       },
+       .probe = mdfld_probe,
+       .remove = mdfld_remove,
+       .id_table = mdfld_hdmi_id,
+
+       .class = I2C_CLASS_DDC,
+       .detect = mdfld_detect,
+       .address_data = &addr_data,
+};
+
+
+static int __init mdfld_i2c_init(void)
+{
+        hdmi_i2c_bus.ddc_client = NULL;
+        hdmi_i2c_bus.hdcp_client = NULL;
+        
+       return i2c_add_driver(&mdfld_hdmi_i2c_driver);
+}
+
+static void __exit mdfld_i2c_exit(void)
+{
+       i2c_del_driver(&mdfld_hdmi_i2c_driver);
+}
+
+
+MODULE_AUTHOR("Chunfeng Zhao <chunfeng.zhao@intel.com>");
+MODULE_DESCRIPTION("mdfld hdmi i2c client driver");
+MODULE_LICENSE("GPL");
+
+module_init(mdfld_i2c_init);
+module_exit(mdfld_i2c_exit);
+#endif  /* FIXME_JLIU7 HDMI */
diff --git a/drivers/staging/mrst/drv/psb_intel_hdmi_i2c.h b/drivers/staging/mrst/drv/psb_intel_hdmi_i2c.h
new file mode 100644 (file)
index 0000000..10a84a6
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef PSB_INTEL_HDMI_I2C_H
+#define PSB_INTEL_HDMI_I2C_H
+
+#if 0 /* FIXME_JLIU7 HDMI */
+struct mdfld_hdmi_i2c {
+        struct i2c_client *ddc_client;
+        struct i2c_client *hdcp_client;
+        int (*open) (struct i2c_client *, void *);
+        int (*close) (struct i2c_client *, void *);
+        char (*read_byte_data)(struct i2c_client *, unsigned char adr);
+        int (*write_byte_data)(struct i2c_client *, unsigned char adr, unsigned char data);
+        int (*read_data)(struct i2c_adapter * adapter,  unsigned char adr, unsigned char * data, int size);
+        int (*write_data)(struct i2c_adapter * adapter, unsigned char adr, unsigned char *data, int size);
+       struct i2c_adapter * (*get_adapter)(struct i2c_client *c);
+        struct mutex lock;
+};
+
+extern struct mdfld_hdmi_i2c * hdmi_i2c_init(void);
+
+#endif /* FIXME_JLIU7 HDMI */
+#endif 
diff --git a/drivers/staging/mrst/drv/psb_intel_hdmi_reg.h b/drivers/staging/mrst/drv/psb_intel_hdmi_reg.h
new file mode 100644 (file)
index 0000000..7596a35
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright Â© 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     
+ */
+/* chunfeng.zhao@intel.com
+  */
+
+#ifndef PSB_INTEL_HDMI_REG_H
+#define PSB_INTEL_HDMI_REG_H
+
+//////////////////////////////////////////
+//
+// Integrated HDMI specific registers
+//
+/////////////////////////////////////////
+
+#define RESERVED2(x,y)  x##y
+#define RESERVED1(x,y)  RESERVED2(x,y)
+#define RANDOMNUMBER   __LINE__        // __COUNTER__
+#define UNIQUENAME(ValueName) RESERVED1(ValueName, RANDOMNUMBER)
+
+/** Requird for HDMI operation */
+#define   HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)
+#define   HDMI_BORDER_ENABLE           (1 << 7)
+#define   HDMI_AUDIO_ENABLE            (1 << 6)
+/** New with 965, default is to be set */
+#define   HDMI_VSYNC_ACTIVE_HIGH       (1 << 4)
+/** New with 965, default is to be set */
+#define   HDMI_HSYNC_ACTIVE_HIGH       (1 << 3)
+#define   HDMIB_PCIE_CONCURRENCY       (1 << 3)
+#define   HDMI_DETECTED                        (1 << 2)
+/* Bits to be preserved when writing */
+#if 0
+#define   HDMIB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
+#define   HDMIC_PRESERVE_MASK ((1 << 17) | (1 << 26))
+#endif 
+//
+//AUDIO configuration register
+//
+#define MDFLD_AUD_CONFIG_REG 0x69000
+       #define MDFLD_AUD_CONFIG_REG_RESERVED_BITS      BITRANGE(31,25)
+typedef union _mdfld_aud_config {
+       uint32_t value;
+       
+       struct
+       {
+               const uint32_t disable_ncts             : 1;    //Bit 0
+               uint32_t lay_out                        : 1;    //Bit 1 (0 - layout 0 1 - layout 1)
+               uint32_t format                         : 2;    /*Bit [3:2] 
+                                                                        * 00 - l-PCM or IEC 61937 
+                                                                         * 01 - High bit rate IEC 61937 stream packet)
+                                                                         * 10 - Not supported
+                                                                         * 11 - Not supported
+                                                                         */
+               uint32_t num_audio_ch                   : 2;    /*Bit [5:4]
+                                                                        * 00 - 2 channels(stereo)
+                                                                        * 01 - 3 or 4 channels
+                                                                        * 10 - 5 or 6 channels
+                                                                        * 11 - 7 or 8 channels
+                                                                        */                             
+               uint32_t UNIQUENAME(Reserved)           : 1;    //Bit 6
+               uint32_t b_bit_enabled                  : 1;    /* Bit 7 (0 - B bit set only for sub-packet 0
+                                                                *        1 - B bit set for all valid sub packet)
+                                                                */
+               uint32_t sample_flat_bit                : 1;    //Bit 8
+               uint32_t validity_bit                   : 1;    //Bit 9 (1 - set V bit in sub-frame 0 - clear V bit(debugging, testing))
+               uint32_t user_bit                       : 1;    //Bit 10 (1 - set U bit in sub frame 0 - clear U bit(default)
+               uint32_t underrun_packet_bit            : 1;    //Bit 11 (1 - send underrun packet 0 - send null packet)
+               uint32_t UNIQUENAME(Reserved)           : 20;   //Bit [31:12]
+       };
+} mdfld_aud_config_t;
+
+//
+// Audio control state register
+//
+#define MDFLD_AUD_CNTL_ST_REG 0x69060
+       #define MDFLD_AUD_CNTL_ST_RESERVED_BITS (BITRANGE(14,4) | BITRANGE(31,25))
+// Note => DIP : Data Island Packet
+typedef union _mdfld_aud_cntl {
+       uint32_t value;
+
+       struct
+       {
+               uint32_t dip_ram_access_address         :4; // bit 3:0
+               uint32_t UNIQUENAME(Reserved)           :11; // bit 14:4
+               uint32_t cp_ready                       :1;     // bit 15 
+               uint32_t video_dip_trans_freq           :2;     // bit 17:16
+               uint32_t dip_buffer_index               :3;     // bit 20:18
+               uint32_t enable_dip_type                :4;     // bit 24:21
+               uint32_t UNIQUENAME(Reserved)           :7;     // bit 31:25
+       };
+       
+} mdfld_aud_cntl_t;
+
+
+// HDMI Audio Data Island Packet Data
+//
+#define MDFLD_HDMI_AUDPAC_DATA_REG 0x69114
+
+typedef union _mdfld_hdmi_audpac_data {
+       uint32_t value;
+
+       struct
+       {
+               uint32_t audio_dip_data                         :32; // bit 31:0
+       };
+} mdfld_hdmi_audpac_data_t;
+
+#endif // PSB_INTEL_HDMI_REG_H
diff --git a/drivers/staging/mrst/drv/psb_intel_reg.h b/drivers/staging/mrst/drv/psb_intel_reg.h
new file mode 100644 (file)
index 0000000..208f82e
--- /dev/null
@@ -0,0 +1,1223 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __PSB_INTEL_REG_H__
+#define __PSB_INTEL_REG_H__
+
+#define BLC_PWM_CTL            0x61254
+#define BLC_PWM_CTL2           0x61250
+#define BLC_PWM_CTL_C          0x62254
+#define BLC_PWM_CTL2_C         0x62250
+#define BACKLIGHT_MODULATION_FREQ_SHIFT                (17)
+/**
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define BACKLIGHT_MODULATION_FREQ_MASK         (0x7fff << 17)
+#define BLM_LEGACY_MODE                                (1 << 16)
+/**
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define BACKLIGHT_DUTY_CYCLE_SHIFT             (0)
+#define BACKLIGHT_DUTY_CYCLE_MASK              (0xffff)
+
+#define I915_GCFGC                     0xf0
+#define I915_LOW_FREQUENCY_ENABLE              (1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ         (0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ             (4 << 4)
+#define I915_DISPLAY_CLOCK_MASK                        (7 << 4)
+
+#define I855_HPLLCC                    0xc0
+#define I855_CLOCK_CONTROL_MASK                        (3 << 0)
+#define I855_CLOCK_133_200                     (0 << 0)
+#define I855_CLOCK_100_200                     (1 << 0)
+#define I855_CLOCK_100_133                     (2 << 0)
+#define I855_CLOCK_166_250                     (3 << 0)
+
+/* I830 CRTC registers */
+#define HTOTAL_A       0x60000
+#define HBLANK_A       0x60004
+#define HSYNC_A        0x60008
+#define VTOTAL_A       0x6000c
+#define VBLANK_A       0x60010
+#define VSYNC_A        0x60014
+#define PIPEASRC       0x6001c
+#define BCLRPAT_A      0x60020
+#define VSYNCSHIFT_A   0x60028
+
+#define HTOTAL_B       0x61000
+#define HBLANK_B       0x61004
+#define HSYNC_B        0x61008
+#define VTOTAL_B       0x6100c
+#define VBLANK_B       0x61010
+#define VSYNC_B        0x61014
+#define PIPEBSRC       0x6101c
+#define BCLRPAT_B      0x61020
+#define VSYNCSHIFT_B   0x61028
+
+#define HTOTAL_C       0x62000
+#define HBLANK_C       0x62004
+#define HSYNC_C        0x62008
+#define VTOTAL_C       0x6200c
+#define VBLANK_C       0x62010
+#define VSYNC_C        0x62014
+#define PIPECSRC       0x6201c
+#define BCLRPAT_C      0x62020
+#define VSYNCSHIFT_C   0x62028
+
+#define PP_STATUS      0x61200
+# define PP_ON                                 (1 << 31)
+/**
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY                              (1 << 30)
+# define PP_SEQUENCE_NONE                      (0 << 28)
+# define PP_SEQUENCE_ON                                (1 << 28)
+# define PP_SEQUENCE_OFF                       (2 << 28)
+# define PP_SEQUENCE_MASK                      0x30000000
+#define PP_CONTROL     0x61204
+# define POWER_TARGET_ON                       (1 << 0)
+
+#define LVDSPP_ON       0x61208
+#define LVDSPP_OFF      0x6120c
+#define PP_CYCLE        0x61210
+
+#define PFIT_CONTROL   0x61230
+# define PFIT_ENABLE                           (1 << 31)
+# define PFIT_PIPE_MASK                                (3 << 29)
+# define PFIT_PIPE_SHIFT                       29
+# define PFIT_PIPE_SELECT_A                    (0 << PFIT_PIPE_SHIFT)
+# define PFIT_PIPE_SELECT_B                    (1 << PFIT_PIPE_SHIFT)
+# define PFIT_PIPE_SELECT_C                    (2 << PFIT_PIPE_SHIFT)
+# define PFIT_PIPE_SELECT_D                    (3 << PFIT_PIPE_SHIFT)
+# define PFIT_SCALING_MODE_PILLARBOX            (1 << 27)
+# define PFIT_SCALING_MODE_LETTERBOX            (3 << 26)
+# define VERT_INTERP_DISABLE                   (0 << 10)
+# define VERT_INTERP_BILINEAR                  (1 << 10)
+# define VERT_INTERP_MASK                      (3 << 10)
+# define VERT_AUTO_SCALE                       (1 << 9)
+# define HORIZ_INTERP_DISABLE                  (0 << 6)
+# define HORIZ_INTERP_BILINEAR                 (1 << 6)
+# define HORIZ_INTERP_MASK                     (3 << 6)
+# define HORIZ_AUTO_SCALE                      (1 << 5)
+# define PANEL_8TO6_DITHER_ENABLE              (1 << 3)
+
+#define PFIT_PGM_RATIOS        0x61234
+# define PFIT_VERT_SCALE_MASK                  0xfff00000
+# define PFIT_HORIZ_SCALE_MASK                 0x0000fff0
+
+#define PFIT_AUTO_RATIOS       0x61238
+
+
+#define DPLL_A         0x06014
+#define DPLL_B         0x06018
+# define DPLL_VCO_ENABLE                       (1 << 31)
+# define DPLL_DVO_HIGH_SPEED                   (1 << 30)
+# define DPLL_SYNCLOCK_ENABLE                  (1 << 29)
+# define DPLL_VGA_MODE_DIS                     (1 << 28)
+# define DPLLB_MODE_DAC_SERIAL                 (1 << 26)       /* i915 */
+# define DPLLB_MODE_LVDS                       (2 << 26)       /* i915 */
+# define DPLL_MODE_MASK                                (3 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10       (0 << 24)       /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5                (1 << 24)       /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14            (0 << 24)       /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7             (1 << 24)       /* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK                        0x03000000      /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK           0x00ff0000      /* i915 */
+/**
+ *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830      0x001f0000
+/**
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
+# define DPLL_FPA01_P1_POST_DIV_SHIFT          16
+# define PLL_P2_DIVIDE_BY_4            (1 << 23)       /* i830, required
+                                                        * in DVO non-gang */
+# define PLL_P1_DIVIDE_BY_TWO                  (1 << 21)       /* i830 */
+# define PLL_REF_INPUT_DREFCLK                 (0 << 13)
+# define PLL_REF_INPUT_TVCLKINA                        (1 << 13)       /* i830 */
+# define PLL_REF_INPUT_TVCLKINBC               (2 << 13)       /* SDVO
+                                                                * TVCLKIN */
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN       (3 << 13)
+# define PLL_REF_INPUT_MASK                    (3 << 13)
+# define PLL_LOAD_PULSE_PHASE_SHIFT            9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK     (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+# define DISPLAY_RATE_SELECT_FPA1      (1 << 8)
+
+/**
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+# define SDVO_MULTIPLIER_MASK                  0x000000ff
+# define SDVO_MULTIPLIER_SHIFT_HIRES           4
+# define SDVO_MULTIPLIER_SHIFT_VGA             0
+
+/** @defgroup DPLL_MD
+ * @{
+ */
+/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD              0x0601c
+/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD              0x06020
+/**
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK              0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT             24
+/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK          0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT         16
+/**
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK           0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT          8
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK       0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT      0
+/** @} */
+
+#define DPLL_TEST              0x606c
+# define DPLLB_TEST_SDVO_DIV_1                 (0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2                 (1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4                 (2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK              (3 << 22)
+# define DPLLB_TEST_N_BYPASS                   (1 << 19)
+# define DPLLB_TEST_M_BYPASS                   (1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE             (1 << 16)
+# define DPLLA_TEST_N_BYPASS                   (1 << 3)
+# define DPLLA_TEST_M_BYPASS                   (1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE             (1 << 0)
+
+#define ADPA                   0x61100
+#define ADPA_DAC_ENABLE        (1<<31)
+#define ADPA_DAC_DISABLE       0
+#define ADPA_PIPE_SELECT_MASK  (1<<30)
+#define ADPA_PIPE_A_SELECT     0
+#define ADPA_PIPE_B_SELECT     (1<<30)
+#define ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define ADPA_SETS_HVPOLARITY   0
+#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define ADPA_VSYNC_CNTL_ENABLE 0
+#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define ADPA_HSYNC_CNTL_ENABLE 0
+#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define ADPA_VSYNC_ACTIVE_LOW  0
+#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define ADPA_HSYNC_ACTIVE_LOW  0
+
+#define FPA0           0x06040
+#define FPA1           0x06044
+#define FPB0           0x06048
+#define FPB1           0x0604c
+# define FP_N_DIV_MASK                         0x003f0000
+# define FP_N_DIV_SHIFT                                16
+# define FP_M1_DIV_MASK                                0x00003f00
+# define FP_M1_DIV_SHIFT                       8
+# define FP_M2_DIV_MASK                                0x0000003f
+# define FP_M2_DIV_SHIFT                       0
+
+
+#define PORT_HOTPLUG_EN                0x61110
+# define SDVOB_HOTPLUG_INT_EN                  (1 << 26)
+# define SDVOC_HOTPLUG_INT_EN                  (1 << 25)
+# define TV_HOTPLUG_INT_EN                     (1 << 18)
+# define CRT_HOTPLUG_INT_EN                    (1 << 9)
+# define CRT_HOTPLUG_FORCE_DETECT              (1 << 3)
+
+#define PORT_HOTPLUG_STAT      0x61114
+# define CRT_HOTPLUG_INT_STATUS                        (1 << 11)
+# define TV_HOTPLUG_INT_STATUS                 (1 << 10)
+# define CRT_HOTPLUG_MONITOR_MASK              (3 << 8)
+# define CRT_HOTPLUG_MONITOR_COLOR             (3 << 8)
+# define CRT_HOTPLUG_MONITOR_MONO              (2 << 8)
+# define CRT_HOTPLUG_MONITOR_NONE              (0 << 8)
+# define SDVOC_HOTPLUG_INT_STATUS              (1 << 7)
+# define SDVOB_HOTPLUG_INT_STATUS              (1 << 6)
+
+#define SDVOB                  0x61140
+#define SDVOC                  0x61160
+#define SDVO_ENABLE                            (1 << 31)
+#define SDVO_PIPE_B_SELECT                     (1 << 30)
+#define SDVO_STALL_SELECT                      (1 << 29)
+#define SDVO_INTERRUPT_ENABLE                  (1 << 26)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define SDVO_PORT_MULTIPLY_MASK                        (7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT               23
+#define SDVO_PHASE_SELECT_MASK                 (15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT              (6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT               (1 << 18)
+#define SDVOC_GANG_MODE                                (1 << 16)
+#define SDVO_BORDER_ENABLE                     (1 << 7)
+#define SDVOB_PCIE_CONCURRENCY                 (1 << 3)
+#define SDVO_DETECTED                          (1 << 2)
+/* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK            ((1 << 17) | (1 << 16) | (1 << 14))
+#define SDVOC_PRESERVE_MASK                    (1 << 17)
+
+/** @defgroup LVDS
+ * @{
+ */
+/**
+ * This register controls the LVDS output enable, pipe selection, and data
+ * format selection.
+ *
+ * All of the clock/data pairs are force powered down by power sequencing.
+ */
+#define LVDS                   0x61180
+/**
+ * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+# define LVDS_PORT_EN                  (1 << 31)
+/** Selects pipe B for LVDS data.  Must be set on pre-965. */
+# define LVDS_PIPEB_SELECT             (1 << 30)
+
+/** Turns on border drawing to allow centered display. */
+# define LVDS_BORDER_EN                 (1 << 15)
+
+/**
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+# define LVDS_A0A2_CLKA_POWER_MASK     (3 << 8)
+# define LVDS_A0A2_CLKA_POWER_DOWN     (0 << 8)
+# define LVDS_A0A2_CLKA_POWER_UP       (3 << 8)
+/**
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+# define LVDS_A3_POWER_MASK            (3 << 6)
+# define LVDS_A3_POWER_DOWN            (0 << 6)
+# define LVDS_A3_POWER_UP              (3 << 6)
+/**
+ * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+# define LVDS_CLKB_POWER_MASK          (3 << 4)
+# define LVDS_CLKB_POWER_DOWN          (0 << 4)
+# define LVDS_CLKB_POWER_UP            (3 << 4)
+
+/**
+ * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode.  The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+# define LVDS_B0B3_POWER_MASK          (3 << 2)
+# define LVDS_B0B3_POWER_DOWN          (0 << 2)
+# define LVDS_B0B3_POWER_UP            (3 << 2)
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE       (1<<31)
+#define PIPEACONF_DISABLE      0
+#define PIPEACONF_DOUBLE_WIDE  (1<<30)
+#define PIPECONF_ACTIVE                (1<<30)
+#define I965_PIPECONF_ACTIVE   (1<<30)
+#define PIPECONF_DSIPLL_LOCK   (1<<29)
+#define PIPEACONF_SINGLE_WIDE  0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_DSR          (1<<26)
+#define PIPEACONF_PIPE_LOCKED  (1<<25)
+#define PIPEACONF_PALETTE      0
+#define PIPECONF_FORCE_BORDER  (1<<25)
+#define PIPEACONF_GAMMA        (1<<24)
+#define PIPECONF_PROGRESSIVE   (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION  (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY                (7 << 21)
+#define PIPECONF_PLANE_OFF     (1<<19)
+#define PIPECONF_CURSOR_OFF    (1<<18)
+
+
+#define PIPEBCONF 0x71008
+#define PIPEBCONF_ENABLE       (1<<31)
+#define PIPEBCONF_DISABLE      0
+#define PIPEBCONF_DOUBLE_WIDE  (1<<30)
+#define PIPEBCONF_DISABLE      0
+#define PIPEBCONF_GAMMA        (1<<24)
+#define PIPEBCONF_PALETTE      0
+
+#define PIPECCONF 0x72008
+
+#define PIPEBGCMAXRED          0x71010
+#define PIPEBGCMAXGREEN                0x71014
+#define PIPEBGCMAXBLUE         0x71018
+
+#define PIPEASTAT               0x70024
+#define PIPEBSTAT              0x71024
+#define PIPECSTAT              0x72024
+#define PIPE_VBLANK_INTERRUPT_STATUS         (1UL<<1)
+#define PIPE_START_VBLANK_INTERRUPT_STATUS   (1UL<<2)
+#define PIPE_VBLANK_CLEAR                    (1 << 1)
+#define PIPE_VBLANK_STATUS                   (1 << 1)
+#define PIPE_TE_STATUS                      (1UL<<6)
+#define PIPE_DPST_EVENT_STATUS              (1UL<<7)
+#define PIPE_VSYNC_CLEAR                     (1UL<<9)
+#define PIPE_VSYNC_STATUS                    (1UL<<9)
+#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS      (1UL<<10)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS   (1UL<<11)
+#define PIPE_VBLANK_INTERRUPT_ENABLE         (1UL<<17)
+#define PIPE_START_VBLANK_INTERRUPT_ENABLE   (1UL<<18)
+#define PIPE_TE_ENABLE                      (1UL<<22)
+#define PIPE_DPST_EVENT_ENABLE               (1UL<<23)
+#define PIPE_VSYNC_ENABL                     (1UL<<25)
+#define PIPE_HDMI_AUDIO_UNDERRUN             (1UL<<26)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE          (1UL<<27)
+#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | PIPE_HDMI_AUDIO_BUFFER_DONE)
+#define PIPE_EVENT_MASK (BIT(29)|BIT(28)|BIT(27)|BIT(26)|BIT(24)|BIT(23)|BIT(22)|BIT(21)|BIT(20)|BIT(16))
+#define PIPE_VBLANK_MASK (BIT(25)|BIT(24)|BIT(18)|BIT(17))
+#define HISTOGRAM_INT_CONTROL          0x61268
+#define HISTOGRAM_BIN_DATA             0X61264
+#define HISTOGRAM_LOGIC_CONTROL                0x61260
+#define PWM_CONTROL_LOGIC              0x61250
+#define PIPE_HOTPLUG_INTERRUPT_STATUS  (1UL<<10)
+#define HISTOGRAM_INTERRUPT_ENABLE     (1UL<<31)
+#define HISTOGRAM_LOGIC_ENABLE         (1UL<<31)
+#define PWM_LOGIC_ENABLE               (1UL<<31)
+#define PWM_PHASEIN_ENABLE             (1UL<<25)
+#define PWM_PHASEIN_INT_ENABLE         (1UL<<24)
+#define PWM_PHASEIN_VB_COUNT           0x00001f00
+#define PWM_PHASEIN_INC                        0x0000001f
+#define HISTOGRAM_INT_CTRL_CLEAR       (1UL<<30)
+#define DPST_YUV_LUMA_MODE             0
+
+struct dpst_ie_histogram_control {
+       union {
+               uint32_t data;
+               struct {
+                       uint32_t bin_reg_index:7;
+                       uint32_t reserved:4;
+                       uint32_t bin_reg_func_select:1;
+                       uint32_t sync_to_phase_in:1;
+                       uint32_t alt_enhancement_mode:2;
+                       uint32_t reserved1:1;
+                       uint32_t sync_to_phase_in_count:8;
+                       uint32_t histogram_mode_select:1;
+                       uint32_t reserved2:4;
+                       uint32_t ie_pipe_assignment:1;
+                       uint32_t ie_mode_table_enabled:1;
+                       uint32_t ie_histogram_enable:1;
+               };
+       };
+};
+
+struct dpst_guardband {
+       union {
+               uint32_t data;
+               struct {
+                       uint32_t guardband:22;
+                       uint32_t guardband_interrupt_delay:8;
+                       uint32_t interrupt_status:1;
+                       uint32_t interrupt_enable:1;
+               };
+       };
+};
+
+#define PIPEAFRAMEHIGH         0x70040
+#define PIPEAFRAMEPIXEL                0x70044
+#define PIPEBFRAMEHIGH         0x71040
+#define PIPEBFRAMEPIXEL                0x71044
+#define PIPECFRAMEHIGH         0x72040
+#define PIPECFRAMEPIXEL                0x72044
+#define PIPE_FRAME_HIGH_MASK    0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT   0
+#define PIPE_FRAME_LOW_MASK     0xff000000
+#define PIPE_FRAME_LOW_SHIFT    24
+#define PIPE_PIXEL_MASK         0x00ffffff
+#define PIPE_PIXEL_SHIFT        0
+
+#define DSPARB                 0x70030
+#define DSPFW1                 0x70034
+#define DSPFW2                 0x70038
+#define DSPFW3                 0x7003c
+#define DSPFW4                 0x70050
+#define DSPFW5                 0x70054
+#define DSPFW6                 0x70058
+#define DSPCHICKENBIT          0x70400
+#define DSPACNTR               0x70180
+#define DSPBCNTR               0x71180
+#define DSPCCNTR               0x72180
+#define DISPLAY_PLANE_ENABLE                   (1<<31)
+#define DISPLAY_PLANE_DISABLE                  0
+#define DISPPLANE_GAMMA_ENABLE                 (1<<30)
+#define DISPPLANE_GAMMA_DISABLE                        0
+#define DISPPLANE_PIXFORMAT_MASK               (0xf<<26)
+#define DISPPLANE_8BPP                         (0x2<<26)
+#define DISPPLANE_15_16BPP                     (0x4<<26)
+#define DISPPLANE_16BPP                                (0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA               (0x6<<26)
+#define DISPPLANE_32BPP                                (0x7<<26)
+#define DISPPLANE_STEREO_ENABLE                        (1<<25)
+#define DISPPLANE_STEREO_DISABLE               0
+#define DISPPLANE_SEL_PIPE_MASK                        (1<<24)
+#define DISPPLANE_SEL_PIPE_POS                 24
+#define DISPPLANE_SEL_PIPE_A                   0
+#define DISPPLANE_SEL_PIPE_B                   (1<<24)
+#define DISPPLANE_SRC_KEY_ENABLE               (1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE              0
+#define DISPPLANE_LINE_DOUBLE                  (1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE               0
+#define DISPPLANE_STEREO_POLARITY_FIRST                0
+#define DISPPLANE_STEREO_POLARITY_SECOND       (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE           (1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE          0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA                0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY         (1)
+#define DISPPLANE_BOTTOM                       (4)
+
+#define DSPABASE               0x70184
+#define DSPALINOFF             0x70184
+#define DSPASTRIDE             0x70188
+
+#define DSPBBASE               0x71184
+#define DSPBLINOFF             0X71184
+#define DSPBADDR               DSPBBASE
+#define DSPBSTRIDE             0x71188
+
+#define DSPCBASE               0x72184
+#define DSPCLINOFF             0x72184
+#define DSPCSTRIDE             0x72188
+
+#define DSPAKEYVAL             0x70194
+#define DSPAKEYMASK            0x70198
+
+#define DSPAPOS                        0x7018C /* reserved */
+#define DSPASIZE               0x70190
+#define DSPBPOS                        0x7118C
+#define DSPBSIZE               0x71190
+#define DSPCPOS                        0x7218C
+#define DSPCSIZE               0x72190
+
+#define DSPASURF               0x7019C
+#define DSPATILEOFF            0x701A4
+
+#define DSPBSURF               0x7119C
+#define DSPBTILEOFF            0x711A4
+
+#define DSPCSURF               0x7219C
+#define DSPCTILEOFF            0x721A4
+#define DSPCKEYMAXVAL          0x721A0
+#define DSPCKEYMINVAL          0x72194
+#define DSPCKEYMSK             0x72198
+
+#define VGACNTRL               0x71400
+# define VGA_DISP_DISABLE                      (1 << 31)
+# define VGA_2X_MODE                           (1 << 30)
+# define VGA_PIPE_B_SELECT                     (1 << 29)
+
+/*
+ * Overlay registers
+ */
+#define OV_C_OFFSET            0x08000
+#define OV_OVADD               0x30000
+#define OV_DOVASTA              0x30008
+# define OV_PIPE_SELECT                                (BIT(6)|BIT(7))
+# define OV_PIPE_SELECT_POS                    6
+# define OV_PIPE_A                             0
+# define OV_PIPE_C                             1
+#define OV_OGAMC5              0x30010
+#define OV_OGAMC4              0x30014
+#define OV_OGAMC3              0x30018
+#define OV_OGAMC2              0x3001C
+#define OV_OGAMC1              0x30020
+#define OV_OGAMC0              0x30024
+#define OVC_OVADD              0x38000
+#define OVC_DOVCSTA             0x38008
+#define OVC_OGAMC5             0x38010
+#define OVC_OGAMC4             0x38014
+#define OVC_OGAMC3             0x38018
+#define OVC_OGAMC2             0x3801C
+#define OVC_OGAMC1             0x38020
+#define OVC_OGAMC0             0x38024
+
+/*
+ * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
+ * of video memory available to the BIOS in SWF1.
+ */ 
+#define SWF0                   0x71410
+#define SWF1                   0x71414
+#define SWF2                   0x71418
+#define SWF3                   0x7141c
+#define SWF4                   0x71420
+#define SWF5                   0x71424
+#define SWF6                   0x71428
+
+/*
+ * 855 scratch registers.
+ */
+#define SWF00                  0x70410
+#define SWF01                  0x70414
+#define SWF02                  0x70418
+#define SWF03                  0x7041c
+#define SWF04                  0x70420
+#define SWF05                  0x70424
+#define SWF06                  0x70428
+
+#define SWF10                  SWF0
+#define SWF11                  SWF1
+#define SWF12                  SWF2
+#define SWF13                  SWF3
+#define SWF14                  SWF4
+#define SWF15                  SWF5
+#define SWF16                  SWF6
+
+#define SWF30                  0x72414
+#define SWF31                  0x72418
+#define SWF32                  0x7241c
+
+
+/*
+ * Palette registers
+ */
+#define PALETTE_A              0x0a000
+#define PALETTE_B              0x0a800
+#define PALETTE_C              0x0ac00
+
+#define IS_I830(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82830_CGC)
+#define IS_845G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82845G_IG)
+#define IS_I85X(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
+#define IS_I855(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
+#define IS_I865G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82865_IG)
+
+
+/* || dev->pci_device == PCI_DEVICE_ID_INTELPCI_CHIP_E7221_G) */
+#define IS_I915G(dev) (dev->pci_device == PCI_DEVICE_ID_INTEL_82915G_IG)
+#define IS_I915GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82915GM_IG)
+#define IS_I945G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945G_IG)
+#define IS_I945GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945GM_IG)
+
+#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
+                      (dev)->pci_device == 0x2982 || \
+                      (dev)->pci_device == 0x2992 || \
+                      (dev)->pci_device == 0x29A2 || \
+                      (dev)->pci_device == 0x2A02 || \
+                      (dev)->pci_device == 0x2A12)
+
+#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
+
+#define IS_G33(dev)    ((dev)->pci_device == 0x29C2 || \
+                       (dev)->pci_device == 0x29B2 ||  \
+                       (dev)->pci_device == 0x29D2)
+
+#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
+                       IS_I945GM(dev) || IS_I965G(dev))
+
+#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
+                               IS_I945GM(dev) || IS_I965GM(dev))
+
+/* Cursor A & B regs */
+#define CURACNTR               0x70080
+#define   CURSOR_MODE_DISABLE   0x00
+#define   CURSOR_MODE_64_32B_AX 0x07
+#define   CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
+#define   MCURSOR_GAMMA_ENABLE  (1 << 26)
+#define CURABASE               0x70084
+#define CURAPOS                        0x70088
+#define   CURSOR_POS_MASK       0x007FF
+#define   CURSOR_POS_SIGN       0x8000
+#define   CURSOR_X_SHIFT        0
+#define   CURSOR_Y_SHIFT        16
+#define CURBCNTR               0x700c0
+#define CURBBASE               0x700c4
+#define CURBPOS                        0x700c8
+#define CURCCNTR               0x700e0
+#define CURCBASE               0x700e4
+#define CURCPOS                        0x700e8
+
+/*
+ * Interrupt Registers
+ */
+#define IER 0x020a0
+#define IIR 0x020a4
+#define IMR 0x020a8
+#define ISR 0x020ac
+
+/*
+ * MOORESTOWN delta registers
+ */
+#define MRST_DPLL_A            0x0f014
+#define MDFLD_DPLL_B           0x0f018
+#define MDFLD_INPUT_REF_SEL    (1 << 14) 
+#define MDFLD_VCO_SEL          (1 << 16) 
+#define DPLLA_MODE_LVDS                (2 << 26)       /* mrst */
+#define MDFLD_PLL_LATCHEN      (1 << 28) 
+#define MDFLD_PWR_GATE_EN      (1 << 30) 
+#define MDFLD_P1_MASK          (0x1FF << 17) 
+#define MRST_FPA0              0x0f040
+#define MRST_FPA1              0x0f044
+#define MDFLD_DPLL_DIV0                0x0f048
+#define MDFLD_DPLL_DIV1                0x0f04c
+#define MRST_PERF_MODE         0x020f4
+
+/* MEDFIELD HDMI registers */
+#define HDMIPHYMISCCTL         0x61134
+# define HDMI_PHY_POWER_DOWN   0x7f
+#define HDMIB_CONTROL          0x61140
+# define HDMIB_PORT_EN                 (1 << 31)
+# define HDMIB_PIPE_B_SELECT           (1 << 30)
+# define HDMIB_NULL_PACKET             (1 << 9)
+#define HDMIB_HDCP_PORT (1 << 5)
+
+/* #define LVDS                        0x61180 */
+# define MRST_PANEL_8TO6_DITHER_ENABLE         (1 << 25)
+# define MRST_PANEL_24_DOT_1_FORMAT            (1 << 24)
+# define LVDS_A3_POWER_UP_0_OUTPUT             (1 << 6)
+
+#define MIPI                   0x61190
+#define MIPI_C                 0x62190
+# define MIPI_PORT_EN                  (1 << 31)
+/** Turns on border drawing to allow centered display. */
+# define SEL_FLOPPED_HSTX              (1 << 23)
+# define PASS_FROM_SPHY_TO_AFE                 (1 << 16)
+# define MIPI_BORDER_EN                        (1 << 15)
+# define MIPIA_3LANE_MIPIC_1LANE       0x1
+# define MIPIA_2LANE_MIPIC_2LANE       0x2
+# define TE_TRIGGER_DSI_PROTOCOL       (1 << 2)
+# define TE_TRIGGER_GPIO_PIN           (1 << 3)
+#define MIPI_TE_COUNT                  0x61194
+
+/* #define PP_CONTROL  0x61204 */
+# define POWER_DOWN_ON_RESET           (1 << 1)
+
+/* #define PFIT_CONTROL        0x61230 */
+# define PFIT_PIPE_SELECT                              (3 << 29)
+# define PFIT_PIPE_SELECT_SHIFT                        (29)
+
+/* #define BLC_PWM_CTL         0x61254 */
+#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT           (16)
+#define MRST_BACKLIGHT_MODULATION_FREQ_MASK            (0xffff << 16)
+
+/* #define PIPEACONF 0x70008 */
+#define PIPEACONF_PIPE_STATE   (1<<30)
+/* #define DSPACNTR            0x70180 */
+#if 0                          /*FIXME JLIU7 need to define the following */
+1000 = 32 - bit RGBX(10 : 10 : 10 : 2)
+pixel format.Ignore alpha.1010 = BGRX 10 : 10 : 10 : 2 1100 = 64 - bit RGBX
+(16 : 16 : 16 : 16) 16 bit floating point pixel format.
+Ignore alpha.1110 = 32 - bit RGBX(8 : 8 : 8 : 8) pixel format.
+    Ignore
+    alpha.
+#endif                         /*FIXME JLIU7 need to define the following */
+
+#define MRST_DSPABASE          0x7019c
+#define MRST_DSPBBASE          0x7119c
+#define MDFLD_DSPCBASE         0x7219c
+
+/*
+ * MOORESTOWN reserved registers
+ */
+#if 0
+#define DSPAPOS                        0x7018C /* reserved */
+#define DSPASIZE               0x70190
+#endif
+/*
+ * Moorestown registers.
+ */
+/*===========================================================================
+; MIPI IP registers
+;--------------------------------------------------------------------------*/
+#define MIPIC_REG_OFFSET             0x800
+#define DEVICE_READY_REG             0xb000
+#define LP_OUTPUT_HOLD               BIT(16)
+#define EXIT_ULPS_DEV_READY          0x3
+#define LP_OUTPUT_HOLD_RELEASE       0x810000
+# define ENTERING_ULPS         (2 << 1)
+# define EXITING_ULPS          (1 << 1)
+# define ULPS_MASK             (3 << 1)
+# define BUS_POSSESSION                (1 << 3)
+#define INTR_STAT_REG                0xb004
+#define RX_SOT_ERROR BIT(0)
+#define RX_SOT_SYNC_ERROR BIT(1)
+#define RX_ESCAPE_MODE_ENTRY_ERROR BIT(3)
+#define RX_LP_TX_SYNC_ERROR BIT(4)
+#define RX_HS_RECEIVE_TIMEOUT_ERROR BIT(5)
+#define RX_FALSE_CONTROL_ERROR BIT(6)
+#define RX_ECC_SINGLE_BIT_ERROR BIT(7)
+#define RX_ECC_MULTI_BIT_ERROR BIT(8)
+#define RX_CHECKSUM_ERROR BIT(9)
+#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED BIT(10)
+#define RX_DSI_VC_ID_INVALID BIT(11)
+#define TX_FALSE_CONTROL_ERROR BIT(12)
+#define TX_ECC_SINGLE_BIT_ERROR BIT(13)
+#define TX_ECC_MULTI_BIT_ERROR BIT(14)
+#define TX_CHECKSUM_ERROR BIT(15)
+#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED BIT(16)
+#define TX_DSI_VC_ID_INVALID BIT(17)
+#define HIGH_CONTENTION BIT(18)
+#define LOW_CONTENTION BIT(19)
+#define DPI_FIFO_UNDER_RUN BIT(20)
+#define HS_TX_TIMEOUT BIT(21)
+#define LP_RX_TIMEOUT BIT(22)
+#define TURN_AROUND_ACK_TIMEOUT BIT(23)
+#define ACK_WITH_NO_ERROR BIT(24)
+#define HS_GENERIC_WR_FIFO_FULL BIT(27)
+#define LP_GENERIC_WR_FIFO_FULL BIT(28)
+#define SPL_PKT_SENT                   BIT(30)
+#define INTR_EN_REG                  0xb008
+#define DSI_FUNC_PRG_REG             0xb00c
+#define DPI_CHANNEL_NUMBER_POS   0x03
+#define DBI_CHANNEL_NUMBER_POS   0x05
+#define FMT_DPI_POS              0x07
+#define FMT_DBI_POS              0x0A
+#define DBI_DATA_WIDTH_POS       0x0D
+/* DPI PIXEL FORMATS */
+#define RGB_565_FMT                 0x01       /* RGB 565 FORMAT */
+#define RGB_666_FMT                 0x02       /* RGB 666 FORMAT */
+#define LRGB_666_FMT                0x03       /* RGB LOOSELY PACKED
+                                                * 666 FORMAT
+                                                */
+#define RGB_888_FMT                 0x04       /* RGB 888 FORMAT */
+#define VIRTUAL_CHANNEL_NUMBER_0       0x00    /* Virtual channel 0 */
+#define VIRTUAL_CHANNEL_NUMBER_1       0x01    /* Virtual channel 1 */
+#define VIRTUAL_CHANNEL_NUMBER_2       0x02    /* Virtual channel 2 */
+#define VIRTUAL_CHANNEL_NUMBER_3       0x03    /* Virtual channel 3 */
+#define DBI_NOT_SUPPORTED              0x00    /* command mode
+                                                * is not supported
+                                                */
+#define DBI_DATA_WIDTH_16BIT           0x01    /* 16 bit data */
+#define DBI_DATA_WIDTH_9BIT                    0x02    /* 9 bit data */
+#define DBI_DATA_WIDTH_8BIT                    0x03    /* 8 bit data */
+#define DBI_DATA_WIDTH_OPT1            0x04    /* option 1 */
+#define DBI_DATA_WIDTH_OPT2            0x05    /* option 2 */
+#define HS_TX_TIMEOUT_REG            0xb010
+#define LP_RX_TIMEOUT_REG            0xb014
+#define TURN_AROUND_TIMEOUT_REG      0xb018
+#define DEVICE_RESET_REG             0xb01C
+#define DPI_RESOLUTION_REG           0xb020
+#define RES_V_POS                0x10
+#define DBI_RESOLUTION_REG           0xb024 /* Reserved for MDFLD */
+#define HORIZ_SYNC_PAD_COUNT_REG     0xb028
+#define HORIZ_BACK_PORCH_COUNT_REG   0xb02C
+#define HORIZ_FRONT_PORCH_COUNT_REG  0xb030
+#define HORIZ_ACTIVE_AREA_COUNT_REG  0xb034
+#define VERT_SYNC_PAD_COUNT_REG      0xb038
+#define VERT_BACK_PORCH_COUNT_REG    0xb03c
+#define VERT_FRONT_PORCH_COUNT_REG   0xb040
+#define HIGH_LOW_SWITCH_COUNT_REG    0xb044
+#define DPI_CONTROL_REG              0xb048
+#define DPI_SHUT_DOWN            BIT(0)
+#define DPI_TURN_ON              BIT(1)
+#define DPI_COLOR_MODE_ON        BIT(2)
+#define DPI_COLOR_MODE_OFF       BIT(3)
+#define DPI_BACK_LIGHT_ON        BIT(4)
+#define DPI_BACK_LIGHT_OFF       BIT(5)
+#define DPI_LP                   BIT(6)
+#define DPI_DATA_REG                 0xb04c
+#define DPI_BACK_LIGHT_ON_DATA   0x07
+#define DPI_BACK_LIGHT_OFF_DATA  0x17
+#define INIT_COUNT_REG               0xb050
+#define MAX_RET_PAK_REG              0xb054
+#define VIDEO_FMT_REG                0xb058
+#define COMPLETE_LAST_PCKT       BIT(2)
+#define EOT_DISABLE_REG              0xb05c
+#define ENABLE_CLOCK_STOPPING    BIT(1)
+#define LP_BYTECLK_REG               0xb060
+#define LP_GEN_DATA_REG              0xb064
+#define HS_GEN_DATA_REG              0xb068
+#define LP_GEN_CTRL_REG              0xb06C
+#define HS_GEN_CTRL_REG              0xb070
+#define DCS_CHANNEL_NUMBER_POS   0x06
+#define MCS_COMMANDS_POS       0x8
+#define WORD_COUNTS_POS                0x8
+#define MCS_PARAMETER_POS      0x10
+#define GEN_FIFO_STAT_REG            0xb074
+#define HS_DATA_FIFO_FULL        BIT(0)
+#define HS_DATA_FIFO_HALF_EMPTY  BIT(1)
+#define HS_DATA_FIFO_EMPTY       BIT(2)
+#define LP_DATA_FIFO_FULL        BIT(8)
+#define LP_DATA_FIFO_HALF_EMPTY  BIT(9)
+#define LP_DATA_FIFO_EMPTY       BIT(10)
+#define HS_CTRL_FIFO_FULL        BIT(16)
+#define HS_CTRL_FIFO_HALF_EMPTY  BIT(17)
+#define HS_CTRL_FIFO_EMPTY       BIT(18)
+#define LP_CTRL_FIFO_FULL        BIT(24)
+#define LP_CTRL_FIFO_HALF_EMPTY  BIT(25)
+#define LP_CTRL_FIFO_EMPTY       BIT(26)
+#define DBI_FIFO_EMPTY           BIT(27)
+#define DPI_FIFO_EMPTY           BIT(28)
+#define HS_LS_DBI_ENABLE_REG         0xb078
+#define TXCLKESC_REG                0xb07c
+#define DPHY_PARAM_REG               0xb080
+#define DBI_BW_CTRL_REG              0xb084
+#define CLK_LANE_SWT_REG             0xb088
+/*===========================================================================
+; MIPI Adapter registers
+;--------------------------------------------------------------------------*/
+#define MIPI_CONTROL_REG             0xb104
+#define MIPI_2X_CLOCK_BITS       (BIT(0) | BIT(1))
+#define MIPI_DATA_ADDRESS_REG        0xb108
+#define MIPI_DATA_LENGTH_REG         0xb10C
+#define MIPI_COMMAND_ADDRESS_REG     0xb110
+#define MIPI_COMMAND_LENGTH_REG      0xb114
+#define MIPI_READ_DATA_RETURN_REG0   0xb118
+#define MIPI_READ_DATA_RETURN_REG1   0xb11C
+#define MIPI_READ_DATA_RETURN_REG2   0xb120
+#define MIPI_READ_DATA_RETURN_REG3   0xb124
+#define MIPI_READ_DATA_RETURN_REG4   0xb128
+#define MIPI_READ_DATA_RETURN_REG5   0xb12C
+#define MIPI_READ_DATA_RETURN_REG6   0xb130
+#define MIPI_READ_DATA_RETURN_REG7   0xb134
+#define MIPI_READ_DATA_VALID_REG     0xb138
+/* DBI COMMANDS */
+#define soft_reset                   0x01
+/* ************************************************************************* *\
+The display module performs a software reset.
+Registers are written with their SW Reset default values.
+\* ************************************************************************* */
+#define get_power_mode               0x0a
+/* ************************************************************************* *\
+The display module returns the current power mode
+\* ************************************************************************* */
+#define get_address_mode             0x0b
+/* ************************************************************************* *\
+The display module returns the current status.
+\* ************************************************************************* */
+#define get_pixel_format             0x0c
+/* ************************************************************************* *\
+This command gets the pixel format for the RGB image data
+used by the interface.
+\* ************************************************************************* */
+#define get_display_mode             0x0d
+/* ************************************************************************* *\
+The display module returns the Display Image Mode status.
+\* ************************************************************************* */
+#define get_signal_mode              0x0e
+/* ************************************************************************* *\
+The display module returns the Display Signal Mode.
+\* ************************************************************************* */
+#define get_diagnostic_result        0x0f
+/* ************************************************************************* *\
+The display module returns the self-diagnostic results following
+a Sleep Out command.
+\* ************************************************************************* */
+#define enter_sleep_mode             0x10
+/* ************************************************************************* *\
+This command causes the display module to enter the Sleep mode.
+In this mode, all unnecessary blocks inside the display module are disabled
+except interface communication. This is the lowest power mode
+the display module supports.
+\* ************************************************************************* */
+#define exit_sleep_mode              0x11
+/* ************************************************************************* *\
+This command causes the display module to exit Sleep mode.
+All blocks inside the display module are enabled.
+\* ************************************************************************* */
+#define enter_partial_mode           0x12
+/* ************************************************************************* *\
+This command causes the display module to enter the Partial Display Mode.
+The Partial Display Mode window is described by the set_partial_area command.
+\* ************************************************************************* */
+#define enter_normal_mode            0x13
+/* ************************************************************************* *\
+This command causes the display module to enter the Normal mode.
+Normal Mode is defined as Partial Display mode and Scroll mode are off
+\* ************************************************************************* */
+#define exit_invert_mode             0x20
+/* ************************************************************************* *\
+This command causes the display module to stop inverting the image data on
+the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define enter_invert_mode            0x21
+/* ************************************************************************* *\
+This command causes the display module to invert the image data only on
+the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_gamma_curve              0x26
+/* ************************************************************************* *\
+This command selects the desired gamma curve for the display device.
+Four fixed gamma curves are defined in section DCS spec.
+\* ************************************************************************* */
+#define set_display_off              0x28
+/* ************************************************************************* *\
+This command causes the display module to stop displaying the image data
+on the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_display_on               0x29
+/* ************************************************************************* *\
+This command causes the display module to start displaying the image data
+on the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_column_address           0x2a
+/* ************************************************************************* *\
+This command defines the column extent of the frame memory accessed by the
+hostprocessor with the read_memory_continue and write_memory_continue commands.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_page_addr             0x2b
+/* ************************************************************************* *\
+This command defines the page extent of the frame memory accessed by the host
+processor with the write_memory_continue and read_memory_continue command.
+No status bits are changed.
+\* ************************************************************************* */
+#define write_mem_start              0x2c
+/* ************************************************************************* *\
+This command transfers image data from the host processor to the display
+module s frame memory starting at the pixel location specified by
+preceding set_column_address and set_page_address commands.
+\* ************************************************************************* */
+#define set_partial_area             0x30
+/* ************************************************************************* *\
+This command defines the Partial Display mode s display area.
+There are two parameters associated with
+this command, the first defines the Start Row (SR) and the second the End Row
+(ER). SR and ER refer to the Frame Memory Line Pointer.
+\* ************************************************************************* */
+#define set_scroll_area              0x33
+/* ************************************************************************* *\
+This command defines the display modules Vertical Scrolling Area.
+\* ************************************************************************* */
+#define set_tear_off                 0x34
+/* ************************************************************************* *\
+This command turns off the display modules Tearing Effect output signal on
+the TE signal line.
+\* ************************************************************************* */
+#define set_tear_on                  0x35
+/* ************************************************************************* *\
+This command turns on the display modules Tearing Effect output signal
+on the TE signal line.
+\* ************************************************************************* */
+#define set_address_mode             0x36
+/* ************************************************************************* *\
+This command sets the data order for transfers from the host processor to
+display modules frame memory,bits B[7:5] and B3, and from the display
+modules frame memory to the display device, bits B[2:0] and B4.
+\* ************************************************************************* */
+#define set_scroll_start             0x37
+/* ************************************************************************* *\
+This command sets the start of the vertical scrolling area in the frame memory.
+The vertical scrolling area is fully defined when this command is used with
+the set_scroll_area command The set_scroll_start command has one parameter,
+the Vertical Scroll Pointer. The VSP defines the line in the frame memory
+that is written to the display device as the first line of the vertical
+scroll area.
+\* ************************************************************************* */
+#define exit_idle_mode               0x38
+/* ************************************************************************* *\
+This command causes the display module to exit Idle mode.
+\* ************************************************************************* */
+#define enter_idle_mode              0x39
+/* ************************************************************************* *\
+This command causes the display module to enter Idle Mode.
+In Idle Mode, color expression is reduced. Colors are shown on the display
+device using the MSB of each of the R, G and B color components in the frame
+memory
+\* ************************************************************************* */
+#define set_pixel_format             0x3a
+/* ************************************************************************* *\
+This command sets the pixel format for the RGB image data used by the interface.
+Bits D[6:4]  DPI Pixel Format Definition
+Bits D[2:0]  DBI Pixel Format Definition
+Bits D7 and D3 are not used.
+\* ************************************************************************* */
+  #define DCS_PIXEL_FORMAT_3bbp                0x1
+  #define DCS_PIXEL_FORMAT_8bbp        0x2
+  #define DCS_PIXEL_FORMAT_12bbp       0x3
+  #define DCS_PIXEL_FORMAT_16bbp       0x5 
+  #define DCS_PIXEL_FORMAT_18bbp       0x6 
+  #define DCS_PIXEL_FORMAT_24bbp       0x7
+#define write_mem_cont               0x3c
+/* ************************************************************************* *\
+This command transfers image data from the host processor to the display
+module's frame memory continuing from the pixel location following the
+previous write_memory_continue or write_memory_start command.
+\* ************************************************************************* */
+#define set_tear_scanline            0x44
+/* ************************************************************************* *\
+This command turns on the display modules Tearing Effect output signal on the
+TE signal line when the display module reaches line N.
+\* ************************************************************************* */
+#define get_scanline                 0x45
+/* ************************************************************************* *\
+The display module returns the current scanline, N, used to update the
+display device. The total number of scanlines on a display device is
+defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as
+the first line of V Sync and is denoted as Line 0.
+When in Sleep Mode, the value returned by get_scanline is undefined.
+\* ************************************************************************* */
+
+/* MCS or Generic COMMANDS */
+/* MCS/generic data type */
+#define GEN_SHORT_WRITE_0      0x03  /* generic short write, no parameters */
+#define GEN_SHORT_WRITE_1      0x13  /* generic short write, 1 parameters */
+#define GEN_SHORT_WRITE_2      0x23  /* generic short write, 2 parameters */
+#define GEN_READ_0             0x04  /* generic read, no parameters */
+#define GEN_READ_1             0x14  /* generic read, 1 parameters */
+#define GEN_READ_2             0x24  /* generic read, 2 parameters */
+#define GEN_LONG_WRITE         0x29  /* generic long write */
+#define MCS_SHORT_WRITE_0      0x05  /* MCS short write, no parameters */
+#define MCS_SHORT_WRITE_1      0x15  /* MCS short write, 1 parameters */
+#define MCS_READ               0x06  /* MCS read, no parameters */
+#define MCS_LONG_WRITE         0x39  /* MCS long write */
+/* MCS/generic commands */
+/*****TPO MCS**********/
+#define write_display_profile          0x50
+#define write_display_brightness       0x51
+#define write_ctrl_display             0x53
+#define write_ctrl_cabc                        0x55
+  #define UI_IMAGE             0x01
+  #define STILL_IMAGE          0x02
+  #define MOVING_IMAGE         0x03
+#define write_hysteresis               0x57
+#define write_gamma_setting            0x58
+#define write_cabc_min_bright          0x5e
+#define write_kbbc_profile             0x60
+/*****TMD MCS**************/
+#define tmd_write_display_brightness 0x8c
+
+/* ************************************************************************* *\
+This command is used to control ambient light, panel backlight brightness and
+gamma settings.
+\* ************************************************************************* */
+#define BRIGHT_CNTL_BLOCK_ON   BIT(5)
+#define AMBIENT_LIGHT_SENSE_ON BIT(4)
+#define DISPLAY_DIMMING_ON     BIT(3)
+#define BACKLIGHT_ON           BIT(2)
+#define DISPLAY_BRIGHTNESS_AUTO        BIT(1)
+#define GAMMA_AUTO             BIT(0)
+
+/* DCS Interface Pixel Formats */
+#define DCS_PIXEL_FORMAT_3BPP         0x1
+#define DCS_PIXEL_FORMAT_8BPP         0x2
+#define DCS_PIXEL_FORMAT_12BPP        0x3
+#define DCS_PIXEL_FORMAT_16BPP        0x5
+#define DCS_PIXEL_FORMAT_18BPP        0x6
+#define DCS_PIXEL_FORMAT_24BPP        0x7
+/* ONE PARAMETER READ DATA */
+#define addr_mode_data           0xfc
+#define diag_res_data            0x00
+#define disp_mode_data           0x23
+#define pxl_fmt_data             0x77
+#define pwr_mode_data            0x74
+#define sig_mode_data            0x00
+/* TWO PARAMETERS READ DATA */
+#define scanline_data1           0xff
+#define scanline_data2           0xff
+#define NON_BURST_MODE_SYNC_PULSE      0x01    /* Non Burst Mode
+                                                * with Sync Pulse
+                                                */
+#define NON_BURST_MODE_SYNC_EVENTS     0x02    /* Non Burst Mode
+                                                * with Sync events
+                                                */
+#define BURST_MODE                     0x03    /* Burst Mode */
+#define DBI_COMMAND_BUFFER_SIZE                0x240  /* 0x32 */    /* 0x120 */        /* Allocate at least
+                                                * 0x100 Byte with 32
+                                                * byte alignment
+                                                */
+#define DBI_DATA_BUFFER_SIZE           0x120   /* Allocate at least
+                                                * 0x100 Byte with 32
+                                                * byte alignment
+                                                */
+#define DBI_CB_TIME_OUT 0xFFFF
+#define GEN_FB_TIME_OUT 2000 
+#define ALIGNMENT_32BYTE_MASK          (~(BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)))
+#define SKU_83                                                 0x01
+#define SKU_100                                        0x02
+#define SKU_100L                                       0x04
+#define SKU_BYPASS                                     0x08
+#if 0
+/* ************************************************************************* *\
+DSI command data structure
+\* ************************************************************************* */
+union DSI_LONG_PACKET_HEADER {
+       u32 DSI_longPacketHeader;
+       struct {
+               u8 dataID;
+               u16 wordCount;
+               u8 ECC;
+       };
+#if 0                          /*FIXME JLIU7 */
+       struct {
+               u8 DT:6;
+               u8 VC:2;
+       };
+#endif                         /*FIXME JLIU7 */
+};
+
+union MIPI_ADPT_CMD_LNG_REG {
+       u32 commnadLengthReg;
+       struct {
+               u8 command0;
+               u8 command1;
+               u8 command2;
+               u8 command3;
+       };
+};
+
+struct SET_COLUMN_ADDRESS_DATA {
+       u8 command;
+       u16 SC;                 /* Start Column */
+       u16 EC;                 /* End Column */
+};
+
+struct SET_PAGE_ADDRESS_DATA {
+       u8 command;
+       u16 SP;                 /* Start Page */
+       u16 EP;                 /* End Page */
+};
+#endif
+
+#endif
diff --git a/drivers/staging/mrst/drv/psb_irq.c b/drivers/staging/mrst/drv/psb_irq.c
new file mode 100644 (file)
index 0000000..902e459
--- /dev/null
@@ -0,0 +1,982 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ **************************************************************************/
+/*
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_page_flip.h"
+#include "psb_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+#include "mdfld_dsi_dbi_dpu.h"
+
+#ifdef CONFIG_MDFD_GL3
+#include "mdfld_gl3.h"
+#endif
+
+/*
+ * inline functions
+ */
+
+static inline u32
+psb_pipestat(int pipe)
+{
+       if (pipe == 0)
+               return PIPEASTAT;
+       if (pipe == 1)
+               return PIPEBSTAT;
+       if (pipe == 2)
+               return PIPECSTAT;
+       BUG();
+}
+
+static inline u32
+mid_pipe_event(int pipe)
+{
+       if (pipe == 0)
+               return _PSB_PIPEA_EVENT_FLAG;
+       if (pipe == 1)
+               return _MDFLD_PIPEB_EVENT_FLAG;
+       if (pipe == 2)
+               return _MDFLD_PIPEC_EVENT_FLAG;
+       BUG();
+}
+
+static inline u32
+mid_pipe_vsync(int pipe)
+{
+       if (pipe == 0)
+               return _PSB_VSYNC_PIPEA_FLAG;
+       if (pipe == 1)
+               return _PSB_VSYNC_PIPEB_FLAG;
+       if (pipe == 2)
+               return _MDFLD_PIPEC_VBLANK_FLAG;
+       BUG();
+}
+
+static inline u32
+mid_pipeconf(int pipe)
+{
+       if (pipe == 0)
+               return PIPEACONF;
+       if (pipe == 1)
+               return PIPEBCONF;
+       if (pipe == 2)
+               return PIPECCONF;
+       BUG();
+}
+
+void
+psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+{
+       if ((dev_priv->pipestat[pipe] & mask) != mask) {
+               u32 reg = psb_pipestat(pipe);
+               dev_priv->pipestat[pipe] |= mask;
+               /* Enable the interrupt, clear any pending status */
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+                       u32 writeVal = PSB_RVDC32(reg);
+                       writeVal |= (mask | (mask >> 16));
+                       PSB_WVDC32(writeVal, reg);
+                       (void) PSB_RVDC32(reg);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               }
+       }
+}
+
+void
+psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+{
+       if ((dev_priv->pipestat[pipe] & mask) != 0) {
+               u32 reg = psb_pipestat(pipe);
+               dev_priv->pipestat[pipe] &= ~mask;
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+                       u32 writeVal = PSB_RVDC32(reg);
+                       writeVal &= ~mask;
+                       PSB_WVDC32(writeVal, reg);
+                       (void) PSB_RVDC32(reg);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               }
+       }
+}
+
+static void
+mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
+{
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               u32 pipe_event = mid_pipe_event(pipe);
+               dev_priv->vdc_irq_mask |= pipe_event;
+               PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+               PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+}
+
+static void
+mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
+{
+       if (dev_priv->pipestat[pipe] == 0) {
+               if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+                       u32 pipe_event = mid_pipe_event(pipe);
+                       dev_priv->vdc_irq_mask &= ~pipe_event;
+                       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+                       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+               }
+       }
+}
+
+/**
+ * Display controller interrupt handler for vsync/vblank.
+ *
+ */
+static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+#if 0 /* FIXME_JLIU7 revisit it*/
+       uint32_t *vbl_received = &dev->vbl_received;
+
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               vbl_received = &dev->vbl_received1;
+               break;
+       case 2:
+               vbl_received = &dev->vbl_received2;
+               break;
+       default:
+               DRM_ERROR("%s, invalded pipe. \n", __FUNCTION__);
+               return;
+       }
+
+
+#ifdef PSB_FIXME
+       atomic_inc(vbl_received);
+#endif
+#endif /* FIXME_JLIU7 revisit it*/
+
+       /**
+        * Using TE interrupt for B0 + command mode panels
+        */
+       if (!is_panel_vid_or_cmd(dev))
+               return;
+
+       drm_handle_vblank(dev, pipe);
+       if (dev_priv->psb_vsync_handler != NULL)
+               (*dev_priv->psb_vsync_handler)(dev, pipe);
+
+       psb_intel_crtc_process_vblank(crtc);
+}
+
+/**
+ * Display controller interrupt handler for pipe hdmi audio underrun.
+ *
+ */
+static void mdfld_pipe_hdmi_audio_underrun(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+
+       if (dev_priv->mdfld_had_event_callbacks)
+               (*dev_priv->mdfld_had_event_callbacks)(HAD_EVENT_AUDIO_BUFFER_UNDERRUN, NULL);
+}
+
+/**
+ * Display controller interrupt handler for pipe hdmi audio buffer done.
+ *
+ */
+static void mdfld_pipe_hdmi_audio_buffer_done(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+
+       if (dev_priv->mdfld_had_event_callbacks)
+               (*dev_priv->mdfld_had_event_callbacks)(HAD_EVENT_AUDIO_BUFFER_DONE, dev_priv->had_pvt_data);
+}
+
+void mdfld_te_handler_work(struct work_struct *work)
+{
+       struct drm_psb_private *dev_priv =
+               container_of(work, struct drm_psb_private, te_work);
+       int pipe = dev_priv->te_pipe;
+       struct drm_device *dev = dev_priv->dev;
+
+#ifdef CONFIG_MDFD_DSI_DPU
+       mdfld_dpu_update_panel(dev);
+#else
+       mdfld_dbi_update_panel(dev, pipe);
+#endif
+
+       /**
+        * Both MIPI panels shares the same system frame buffer
+        * only need to unblock X when the primary panel's TE happens.
+        * FIXME: how to avoid tearing on MIPI1???
+        */
+       if (pipe == 0) {
+               drm_handle_vblank(dev, pipe);
+
+               if (dev_priv->psb_vsync_handler != NULL)
+                       (*dev_priv->psb_vsync_handler)(dev, pipe);
+       }
+}
+/**
+ * Display controller interrupt handler for pipe event.
+ *
+ */
+#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff
+static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+
+       uint32_t pipe_stat_val = 0;
+       uint32_t pipe_stat_reg = psb_pipestat(pipe);
+       uint32_t pipe_enable = dev_priv->pipestat[pipe];
+       uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
+       uint32_t i = 0;
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irq_flags);
+
+       pipe_stat_val = PSB_RVDC32(pipe_stat_reg);
+       pipe_stat_val &= pipe_enable | pipe_status;
+       pipe_stat_val &= pipe_stat_val >> 16;
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irq_flags);
+
+       /* clear the 2nd level interrupt status bits */
+       /**
+       * FIXME: shouldn't use while loop here. However, the interrupt
+       * status 'sticky' bits cannot be cleared by setting '1' to that
+       * bit once...
+       */
+       for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i ++) {
+               PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
+               (void) PSB_RVDC32(pipe_stat_reg);
+
+               if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)
+                       break;
+       }
+
+       if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
+               DRM_ERROR("%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x. \n",
+                         __FUNCTION__, PSB_RVDC32(pipe_stat_reg));
+
+       if ((pipe_stat_val & PIPE_DPST_EVENT_STATUS) &&
+           (dev_priv->psb_dpst_state != NULL)) {
+               uint32_t pwm_reg = 0;
+               uint32_t hist_reg = 0;
+               u32 irqCtrl = 0;
+               struct dpst_guardband guardband_reg;
+               struct dpst_ie_histogram_control ie_hist_cont_reg;
+
+               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+               /* Determine if this is histogram or pwm interrupt */
+               if (hist_reg & HISTOGRAM_INT_CTRL_CLEAR) {
+                       /* Notify UM of histogram interrupt */
+                       psb_dpst_notify_change_um(DPST_EVENT_HIST_INTERRUPT,
+                                                 dev_priv->psb_dpst_state);
+
+                       /* disable dpst interrupts */
+                       guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+                       guardband_reg.interrupt_enable = 0;
+                       guardband_reg.interrupt_status = 1;
+                       PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
+
+                       ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+                       ie_hist_cont_reg.ie_histogram_enable = 0;
+                       PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
+
+                       irqCtrl = PSB_RVDC32(PIPEASTAT);
+                       irqCtrl &= ~PIPE_DPST_EVENT_ENABLE;
+                       PSB_WVDC32(irqCtrl, PIPEASTAT);
+               }
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+               if ((pwm_reg & PWM_PHASEIN_INT_ENABLE) &&
+                   !(pwm_reg & PWM_PHASEIN_ENABLE)) {
+                       /* Notify UM of the phase complete */
+                       psb_dpst_notify_change_um(DPST_EVENT_PHASE_COMPLETE,
+                                                 dev_priv->psb_dpst_state);
+
+                       /* Temporarily get phase mngr ready to generate
+                        * another interrupt until this can be moved to
+                        * user mode */
+                       /* PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
+                                  PWM_CONTROL_LOGIC); */
+               }
+       }
+
+       if (pipe_stat_val & PIPE_VBLANK_STATUS) {
+               mid_vblank_handler(dev, pipe);
+       }
+
+       if (pipe_stat_val & PIPE_TE_STATUS) {
+               dev_priv->te_pipe = pipe;
+               schedule_work(&dev_priv->te_work);
+       }
+
+       if (pipe_stat_val & PIPE_HDMI_AUDIO_UNDERRUN_STATUS) {
+               mdfld_pipe_hdmi_audio_underrun(dev);
+       }
+
+       if (pipe_stat_val & PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS) {
+               mdfld_pipe_hdmi_audio_buffer_done(dev);
+       }
+}
+
+/**
+ * Display controller interrupt handler.
+ */
+static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
+{
+
+       if (vdc_stat & _PSB_PIPEA_EVENT_FLAG) {
+               mid_pipe_event_handler(dev, 0);
+       }
+
+       if (vdc_stat & _MDFLD_PIPEB_EVENT_FLAG) {
+               mid_pipe_event_handler(dev, 1);
+       }
+
+       if (vdc_stat & _MDFLD_PIPEC_EVENT_FLAG) {
+               mid_pipe_event_handler(dev, 2);
+       }
+
+       if (vdc_stat & _MDFLD_MIPIA_FLAG) {
+               /* mid_mipi_event_handler(dev, 0); */
+       }
+
+       if (vdc_stat & _MDFLD_MIPIC_FLAG) {
+               /* mid_mipi_event_handler(dev, 2); */
+       }
+}
+
+/**
+ * Medfield Gl3 Cache interrupt handler.
+ */
+#ifdef CONFIG_MDFD_GL3
+static void mdfld_gl3_interrupt(struct drm_device *dev, uint32_t vdc_stat)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       uint32_t gl3_err_status = 0;
+
+       gl3_err_status = MDFLD_GL3_READ(MDFLD_GCL_ERR_STATUS);
+       if (gl3_err_status & _MDFLD_GL3_ECC_FLAG) {
+               gl3_flush();
+               gl3_reset();
+       }
+
+       dev_priv->vdc_irq_mask &= ~_MDFLD_GL3_IRQ_FLAG;
+       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+}
+#endif
+
+
+irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+
+       uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, msvdx_int = 0, topaz_int = 0;
+       int handled = 0;
+       unsigned long irq_flags;
+
+#ifdef CONFIG_MDFD_GL3
+       uint32_t gl3_int = 0;
+#endif
+
+       /*      PSB_DEBUG_ENTRY("\n"); */
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irq_flags);
+
+       vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+
+       if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) {
+               PSB_DEBUG_IRQ("Got DISP interrupt\n");
+               dsp_int = 1;
+       }
+
+       if (vdc_stat & _PSB_IRQ_SGX_FLAG) {
+               PSB_DEBUG_IRQ("Got SGX interrupt\n");
+               sgx_int = 1;
+       }
+       if (vdc_stat & _PSB_IRQ_MSVDX_FLAG) {
+               PSB_DEBUG_IRQ("Got MSVDX interrupt\n");
+               msvdx_int = 1;
+       }
+
+       if (vdc_stat & _LNC_IRQ_TOPAZ_FLAG) {
+               PSB_DEBUG_IRQ("Got TOPAX interrupt\n");
+               topaz_int = 1;
+       }
+
+#ifdef CONFIG_MDFD_GL3
+       if (vdc_stat & _MDFLD_GL3_IRQ_FLAG) {
+               PSB_DEBUG_IRQ("Got GL3 interrupt\n");
+               gl3_int = 1;
+       }
+#endif
+
+       vdc_stat &= dev_priv->vdc_irq_mask;
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irq_flags);
+
+       if (dsp_int && ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+               psb_vdc_interrupt(dev, vdc_stat);
+               handled = 1;
+       }
+
+       if (msvdx_int) {
+               psb_msvdx_interrupt(dev);
+               handled = 1;
+       }
+
+       if (topaz_int) {
+               pnw_topaz_interrupt(dev);
+               handled = 1;
+       }
+
+       if (sgx_int) {
+               if (SYSPVRServiceSGXInterrupt(dev) != 0)
+                       handled = 1;
+       }
+
+#ifdef CONFIG_MDFD_GL3
+       if (gl3_int) {
+               mdfld_gl3_interrupt(dev, vdc_stat);
+               handled = 1;
+       }
+#endif
+
+       PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
+       (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
+       DRM_READMEMORYBARRIER();
+
+       if (!handled)
+               return IRQ_NONE;
+
+       return IRQ_HANDLED;
+}
+
+void psb_irq_preinstall(struct drm_device *dev)
+{
+       psb_irq_preinstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+/**
+ * FIXME: should I remove display irq enable here??
+ */
+void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       if (hw_islands & OSPM_DISPLAY_ISLAND) {
+               if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+                       if (dev->vblank_enabled[0])
+                               dev_priv->vdc_irq_mask |= _PSB_PIPEA_EVENT_FLAG;
+                       if (dev->vblank_enabled[1])
+                               dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
+                       if (dev->vblank_enabled[2])
+                               dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
+               }
+       }
+       if (hw_islands & OSPM_GRAPHICS_ISLAND) {
+               dev_priv->vdc_irq_mask |= _PSB_IRQ_SGX_FLAG;
+#ifdef CONFIG_MDFD_GL3
+               dev_priv->vdc_irq_mask |= _MDFLD_GL3_IRQ_FLAG;
+#endif
+       }
+
+       if (hw_islands & OSPM_VIDEO_DEC_ISLAND)
+               if (ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND))
+                       dev_priv->vdc_irq_mask |= _PSB_IRQ_MSVDX_FLAG;
+
+       if (hw_islands & OSPM_VIDEO_ENC_ISLAND)
+               if (ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
+                       dev_priv->vdc_irq_mask |= _LNC_IRQ_TOPAZ_FLAG;
+
+       /*This register is safe even if display island is off*/
+       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+int psb_irq_postinstall(struct drm_device *dev)
+{
+       return psb_irq_postinstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+int psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands)
+{
+
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       /*This register is safe even if display island is off*/
+       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+       if (hw_islands & OSPM_DISPLAY_ISLAND) {
+               if (true/*powermgmt_is_hw_on(dev->pdev, PSB_DISPLAY_ISLAND)*/) {
+                       if (dev->vblank_enabled[0])
+                               psb_enable_pipestat(dev_priv, 0,
+                                                   PIPE_VBLANK_INTERRUPT_ENABLE);
+                       else
+                               psb_disable_pipestat(dev_priv, 0,
+                                                    PIPE_VBLANK_INTERRUPT_ENABLE);
+
+                       if (dev->vblank_enabled[1])
+                               psb_enable_pipestat(dev_priv, 1,
+                                                   PIPE_VBLANK_INTERRUPT_ENABLE);
+                       else
+                               psb_disable_pipestat(dev_priv, 1,
+                                                    PIPE_VBLANK_INTERRUPT_ENABLE);
+
+                       if (dev->vblank_enabled[2])
+                               psb_enable_pipestat(dev_priv, 2,
+                                                   PIPE_VBLANK_INTERRUPT_ENABLE);
+                       else
+                               psb_disable_pipestat(dev_priv, 2,
+                                                    PIPE_VBLANK_INTERRUPT_ENABLE);
+               }
+       }
+
+       if (!dev_priv->topaz_disabled)
+               if (hw_islands & OSPM_VIDEO_ENC_ISLAND)
+                       if (ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
+                               pnw_topaz_enableirq(dev);
+
+       if (hw_islands & OSPM_VIDEO_DEC_ISLAND)
+               if (true/*powermgmt_is_hw_on(dev->pdev, PSB_VIDEO_DEC_ISLAND)*/)
+                       psb_msvdx_enableirq(dev);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+       return 0;
+}
+
+void psb_irq_uninstall(struct drm_device *dev)
+{
+       psb_irq_uninstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       if (hw_islands & OSPM_DISPLAY_ISLAND) {
+               if (true/*powermgmt_is_hw_on(dev->pdev, PSB_DISPLAY_ISLAND)*/) {
+                       if (dev->vblank_enabled[0])
+                               psb_disable_pipestat(dev_priv, 0,
+                                                    PIPE_VBLANK_INTERRUPT_ENABLE);
+
+                       if (dev->vblank_enabled[1])
+                               psb_disable_pipestat(dev_priv, 1,
+                                                    PIPE_VBLANK_INTERRUPT_ENABLE);
+
+                       if (dev->vblank_enabled[2])
+                               psb_disable_pipestat(dev_priv, 2,
+                                                    PIPE_VBLANK_INTERRUPT_ENABLE);
+               }
+               dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
+                                         _PSB_IRQ_MSVDX_FLAG |
+                                         _LNC_IRQ_TOPAZ_FLAG;
+#ifdef CONFIG_MDFD_GL3
+               dev_priv->vdc_irq_mask &= _MDFLD_GL3_IRQ_FLAG;
+#endif
+       }
+       /*TODO: remove follwoing code*/
+       if (hw_islands & OSPM_GRAPHICS_ISLAND) {
+               dev_priv->vdc_irq_mask &= ~_PSB_IRQ_SGX_FLAG;
+#ifdef CONFIG_MDFD_GL3
+               dev_priv->vdc_irq_mask &= ~_MDFLD_GL3_IRQ_FLAG;
+#endif
+       }
+
+       if (hw_islands & OSPM_VIDEO_DEC_ISLAND)
+               dev_priv->vdc_irq_mask &= ~_PSB_IRQ_MSVDX_FLAG;
+
+       if (hw_islands & OSPM_VIDEO_ENC_ISLAND)
+               dev_priv->vdc_irq_mask &= ~_LNC_IRQ_TOPAZ_FLAG;
+
+       /*These two registers are safe even if display island is off*/
+       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+       wmb();
+
+       /*This register is safe even if display island is off*/
+       PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
+
+       if (!dev_priv->topaz_disabled)
+               if (hw_islands & OSPM_VIDEO_ENC_ISLAND)
+                       if (ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
+                               pnw_topaz_disableirq(dev);
+       if (hw_islands & OSPM_VIDEO_DEC_ISLAND)
+               if (ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND))
+                       psb_msvdx_disableirq(dev);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+void psb_irq_turn_on_dpst(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       u32 hist_reg;
+       u32 pwm_reg;
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               PSB_WVDC32(BIT(31), HISTOGRAM_LOGIC_CONTROL);
+               hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+               PSB_WVDC32(BIT(31), HISTOGRAM_INT_CONTROL);
+               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+               PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC);
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+               PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE | PWM_PHASEIN_INT_ENABLE,
+                          PWM_CONTROL_LOGIC);
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+               psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
+
+               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+               PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR, HISTOGRAM_INT_CONTROL);
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+               PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, PWM_CONTROL_LOGIC);
+
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+}
+
+int psb_irq_enable_dpst(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       /* enable DPST */
+       mid_enable_pipe_event(dev_priv, 0);
+       psb_irq_turn_on_dpst(dev);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+       return 0;
+}
+
+void psb_irq_turn_off_dpst(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       u32 hist_reg;
+       u32 pwm_reg;
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
+               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+               psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
+
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+               PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), PWM_CONTROL_LOGIC);
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+}
+
+int psb_irq_disable_dpst(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       mid_disable_pipe_event(dev_priv, 0);
+       psb_irq_turn_off_dpst(dev);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+       return 0;
+}
+
+#ifdef PSB_FIXME
+static int psb_vblank_do_wait(struct drm_device *dev,
+                             unsigned int *sequence, atomic_t *counter)
+{
+       unsigned int cur_vblank;
+       int ret = 0;
+       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+                   (((cur_vblank = atomic_read(counter))
+                     - *sequence) <= (1 << 23)));
+       *sequence = cur_vblank;
+
+       return ret;
+}
+#endif
+
+/*
+ * It is used to enable VBLANK interrupt
+ */
+int psb_enable_vblank(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+       uint32_t reg_val = 0;
+       uint32_t pipeconf_reg = mid_pipeconf(pipe);
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if (!is_panel_vid_or_cmd(dev))
+               return mdfld_enable_te(dev, pipe);
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               reg_val = REG_READ(pipeconf_reg);
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+
+       if (!(reg_val & PIPEACONF_ENABLE))
+               return -EINVAL;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       drm_psb_disable_vsync = 0;
+       mid_enable_pipe_event(dev_priv, pipe);
+       psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+       return 0;
+}
+
+/*
+ * It is used to disable VBLANK interrupt
+ */
+void psb_disable_vblank(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if (!is_panel_vid_or_cmd(dev))
+               mdfld_disable_te(dev, pipe);
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       drm_psb_disable_vsync = 1;
+       mid_disable_pipe_event(dev_priv, pipe);
+       psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+/* Called from drm generic code, passed a 'crtc', which
+ * we use as a pipe index
+ */
+u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
+{
+       uint32_t high_frame = PIPEAFRAMEHIGH;
+       uint32_t low_frame = PIPEAFRAMEPIXEL;
+       uint32_t pipeconf_reg = PIPEACONF;
+       uint32_t reg_val = 0;
+       uint32_t high1 = 0, high2 = 0, low = 0, count = 0;
+
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               high_frame = PIPEBFRAMEHIGH;
+               low_frame = PIPEBFRAMEPIXEL;
+               pipeconf_reg = PIPEBCONF;
+               break;
+       case 2:
+               high_frame = PIPECFRAMEHIGH;
+               low_frame = PIPECFRAMEPIXEL;
+               pipeconf_reg = PIPECCONF;
+               break;
+       default:
+               DRM_ERROR("%s, invalded pipe. \n", __FUNCTION__);
+               return 0;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, false))
+               return 0;
+
+       reg_val = REG_READ(pipeconf_reg);
+
+       if (!(reg_val & PIPEACONF_ENABLE)) {
+               DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+               goto psb_get_vblank_counter_exit;
+       }
+
+       /*
+        * High & low register fields aren't synchronized, so make sure
+        * we get a low value that's stable across two reads of the high
+        * register.
+        */
+       do {
+               high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+                        PIPE_FRAME_HIGH_SHIFT);
+               low = ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+                      PIPE_FRAME_LOW_SHIFT);
+               high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+                        PIPE_FRAME_HIGH_SHIFT);
+       } while (high1 != high2);
+
+       count = (high1 << 8) | low;
+
+psb_get_vblank_counter_exit:
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       return count;
+}
+
+/*
+ * It is used to enable TE interrupt
+ */
+int mdfld_enable_te(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+       uint32_t reg_val = 0;
+       uint32_t pipeconf_reg = mid_pipeconf(pipe);
+
+       PSB_DEBUG_ENTRY("pipe = %d, \n", pipe);
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               reg_val = REG_READ(pipeconf_reg);
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+
+       if (!(reg_val & PIPEACONF_ENABLE))
+               return -EINVAL;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       mid_enable_pipe_event(dev_priv, pipe);
+       psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+       return 0;
+}
+
+/*
+ * It is used to disable TE interrupt
+ */
+void mdfld_disable_te(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if (!dev_priv->b_dsr_enable)
+               return;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       mid_disable_pipe_event(dev_priv, pipe);
+       psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+int mdfld_irq_enable_hdmi_audio(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+       u32 reg_val = 0, mask = 0;
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+               reg_val = REG_READ(PIPEBCONF);
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+
+       if (!(reg_val & PIPEACONF_ENABLE))
+               return -EINVAL;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       /* enable HDMI audio interrupt*/
+       mid_enable_pipe_event(dev_priv, 1);
+       dev_priv->pipestat[1] &= ~PIPE_HDMI_AUDIO_INT_MASK;
+       mask = dev_priv->hdmi_audio_interrupt_mask;
+       psb_enable_pipestat(dev_priv, 1, mask);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+       return 0;
+}
+
+int mdfld_irq_disable_hdmi_audio(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       mid_disable_pipe_event(dev_priv, 1);
+       psb_disable_pipestat(dev_priv, 1, PIPE_HDMI_AUDIO_INT_MASK);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+       return 0;
+}
diff --git a/drivers/staging/mrst/drv/psb_irq.h b/drivers/staging/mrst/drv/psb_irq.h
new file mode 100644 (file)
index 0000000..5b11639
--- /dev/null
@@ -0,0 +1,57 @@
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ **************************************************************************/
+
+#ifndef _PSB_IRQ_H_
+#define _PSB_IRQ_H_
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+
+void psb_irq_preinstall(struct drm_device *dev);
+int  psb_irq_postinstall(struct drm_device *dev);
+void psb_irq_uninstall(struct drm_device *dev);
+irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+
+void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands);
+int  psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands);
+void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
+
+int psb_irq_enable_dpst(struct drm_device *dev);
+int psb_irq_disable_dpst(struct drm_device *dev);
+void psb_irq_turn_on_dpst(struct drm_device *dev);
+void psb_irq_turn_off_dpst(struct drm_device *dev);
+int  psb_enable_vblank(struct drm_device *dev, int pipe);
+void psb_disable_vblank(struct drm_device *dev, int pipe);
+u32  psb_get_vblank_counter(struct drm_device *dev, int pipe);
+
+void psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+void psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+
+int mdfld_enable_te(struct drm_device *dev, int pipe);
+void mdfld_disable_te(struct drm_device *dev, int pipe);
+int mdfld_irq_enable_hdmi_audio(struct drm_device *dev);
+int mdfld_irq_disable_hdmi_audio(struct drm_device *dev);
+void psb_te_timer_func(unsigned long data);
+void mdfld_te_handler_work(struct work_struct *te_work);
+
+#endif /* _PSB_IRQ_H_ */
diff --git a/drivers/staging/mrst/drv/psb_page_flip.c b/drivers/staging/mrst/drv/psb_page_flip.c
new file mode 100644 (file)
index 0000000..dfde9b0
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,·
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+ * Pauli Nieminen <pauli.nieminen@intel.com>
+ *
+ */
+
+#include <linux/spinlock.h>
+#include <linux/list.h>
+
+#include <drm/drmP.h>
+#include "psb_fb.h"
+#include "psb_intel_reg.h"
+#include "psb_page_flip.h"
+#include "psb_pvr_glue.h"
+
+#include "mdfld_output.h"
+#include "mdfld_dsi_output.h"
+
+#if defined(CONFIG_MDFLD_DUAL_DSI_DPU)
+#include "mdfld_dsi_dbi_dpu.h"
+#elif defined(CONFIG_MDFLD_DSI_DSR)
+#include "mdfld_dsi_dbi.h"
+#endif
+
+struct pending_flip {
+       struct drm_crtc *crtc;
+       struct drm_pending_vblank_event *event;
+       PVRSRV_KERNEL_MEM_INFO *old_mem_info;
+       uint32_t offset;
+};
+
+static void
+send_page_flip_event(struct drm_device *dev, int pipe,
+                    struct pending_flip *pending_flip)
+{
+       struct drm_pending_vblank_event *e;
+       struct timeval now;
+       struct drm_file *file_priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+
+       if (pending_flip->event) {
+               file_priv = e->base.file_priv;
+               e = pending_flip->event;
+               do_gettimeofday(&now);
+               e->event.sequence = drm_vblank_count(dev, pipe);
+               e->event.tv_sec = now.tv_sec;
+               e->event.tv_usec = now.tv_usec;
+               list_add_tail(&e->base.link,
+                             &e->base.file_priv->event_list);
+               wake_up_interruptible(&e->base.file_priv->event_wait);
+       }
+
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static void
+write_scanout_regs(struct pending_flip *pending_flip, uint32_t offset)
+{
+       struct drm_device *dev = pending_flip->crtc->dev;
+       struct psb_intel_crtc *psb_intel_crtc =
+               to_psb_intel_crtc(pending_flip->crtc);
+
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       int reg_offset;
+
+       switch (psb_intel_crtc->pipe) {
+       case 0:
+               reg_offset = DSPASURF;
+               break;
+       case 1:
+               reg_offset = DSPBSURF;
+               break;
+       case 2:
+               reg_offset = DSPCSURF;
+               break;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+                                      OSPM_UHB_FORCE_POWER_ON))
+               return;
+
+       iowrite32(offset, dev_priv->vdc_reg + reg_offset);
+
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static void
+increase_read_ops_pending(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+       psKernelMemInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+}
+
+static void
+increase_read_ops_completed(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+       psKernelMemInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+}
+
+static PVRSRV_KERNEL_MEM_INFO *
+get_fb_meminfo(struct drm_framebuffer *fb)
+{
+       struct psb_framebuffer *psbfb = to_psb_fb(fb);
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+       if (psb_get_meminfo_by_handle(psbfb->hKernelMemInfo, &psKernelMemInfo))
+               return NULL;
+
+       return psKernelMemInfo;
+}
+
+static void
+psb_intel_flip_complete(struct pending_flip *pending_flip)
+{
+       if (pending_flip) {
+               struct drm_crtc *crtc = pending_flip->crtc;
+               struct drm_device *dev = crtc->dev;
+               struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+               int pipe = psb_intel_crtc->pipe;
+
+               send_page_flip_event(dev, pipe, pending_flip);
+               drm_vblank_put(dev, pipe);
+               increase_read_ops_completed(pending_flip->old_mem_info);
+               PVRSRVScheduleDeviceCallbacks();
+
+               kfree(pending_flip);
+       }
+}
+
+void
+psb_intel_crtc_process_vblank(struct drm_crtc *crtc)
+{
+       struct pending_flip *pending_flip = NULL;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+       pending_flip = xchg(&psb_intel_crtc->pending_flip, NULL);
+
+       psb_intel_flip_complete(pending_flip);
+}
+
+static void
+sync_callback(void *data)
+{
+       struct pending_flip *pending_flip = data;
+
+       struct drm_crtc* crtc = pending_flip->crtc;
+       struct drm_device *dev = crtc->dev;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+       write_scanout_regs(pending_flip, pending_flip->offset);
+
+       pending_flip = xchg(&psb_intel_crtc->pending_flip, pending_flip);
+
+       drm_vblank_get(dev, psb_intel_crtc->pipe);
+
+       psb_intel_flip_complete(pending_flip);
+}
+
+int
+psb_intel_crtc_page_flip(struct drm_crtc *crtc,
+                         struct drm_framebuffer *fb,
+                         struct drm_pending_vblank_event *event)
+{
+       struct psb_framebuffer *psbfb = to_psb_fb(fb);
+       PVRSRV_KERNEL_MEM_INFO *new_fb_mem_info, *current_fb_mem_info;
+       struct pending_flip *new_pending_flip;
+       int ret;
+
+       if (psb_get_meminfo_by_handle(psbfb->hKernelMemInfo, &new_fb_mem_info))
+               return -EINVAL;
+
+       new_pending_flip = kmalloc(sizeof *new_pending_flip, GFP_KERNEL);
+       if (!new_pending_flip)
+               return -ENOMEM;
+
+       new_pending_flip->crtc = crtc;
+       new_pending_flip->event = event;
+       new_pending_flip->offset = psbfb->offset;
+
+       current_fb_mem_info = get_fb_meminfo(crtc->fb);
+
+       crtc->fb = fb;
+
+       BUG_ON(!current_fb_mem_info);
+       new_pending_flip->old_mem_info = current_fb_mem_info;
+
+       increase_read_ops_pending(current_fb_mem_info);
+
+       ret = PVRSRVCallbackOnSync(new_fb_mem_info->psKernelSyncInfo,
+                                  PVRSRV_SYNC_WRITE, sync_callback,
+                                  new_pending_flip);
+       if (ret < 0)
+               kfree(new_pending_flip);
+
+       return ret;
+}
diff --git a/drivers/staging/mrst/drv/psb_page_flip.h b/drivers/staging/mrst/drv/psb_page_flip.h
new file mode 100644 (file)
index 0000000..41c8b6b
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,·
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+ *
+ */
+
+#ifndef _PSB_PAGE_FLIP_H_
+#define _PSB_PAGE_FLIP_H_
+
+void psb_intel_crtc_process_vblank(struct drm_crtc *crtc);
+int psb_intel_crtc_page_flip(struct drm_crtc *crtc,
+                             struct drm_framebuffer *fb,
+                             struct drm_pending_vblank_event *event);
+
+#endif /* _PSB_PAGE_FLIP_H_ */
diff --git a/drivers/staging/mrst/drv/psb_powermgmt.c b/drivers/staging/mrst/drv/psb_powermgmt.c
new file mode 100644 (file)
index 0000000..d14de22
--- /dev/null
@@ -0,0 +1,1874 @@
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ */
+#include "psb_powermgmt.h"
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include <linux/mutex.h>
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include <asm/intel_scu_ipc.h>
+
+#undef OSPM_GFX_DPK
+
+extern IMG_UINT32 gui32SGXDeviceID;
+extern IMG_UINT32 gui32MRSTDisplayDeviceID;
+extern IMG_UINT32 gui32MRSTMSVDXDeviceID;
+extern IMG_UINT32 gui32MRSTTOPAZDeviceID;
+
+struct drm_device *gpDrmDevice = NULL;
+static struct mutex g_ospm_mutex;
+static bool gbSuspendInProgress = false;
+static bool gbResumeInProgress = false;
+static int g_hw_power_status_mask;
+static atomic_t g_display_access_count;
+static atomic_t g_graphics_access_count;
+static atomic_t g_videoenc_access_count;
+static atomic_t g_videodec_access_count;
+
+void ospm_power_island_up(int hw_islands);
+void ospm_power_island_down(int hw_islands);
+static bool gbSuspended = false;
+bool gbgfxsuspended = false;
+bool gbdispstatus = true;
+
+
+#ifdef CONFIG_PM_RUNTIME
+int enable_gfx_rtpm = 0;
+
+void psb_runtimepm_wq_handler(struct work_struct *work)
+{
+       struct drm_psb_private * dev_priv =  gpDrmDevice->dev_private;
+
+       if(drm_psb_ospm && !enable_gfx_rtpm) {
+               printk(KERN_ALERT "Enable GFX runtime_pm \n");
+
+               dev_priv->rpm_enabled = 1;
+
+               enable_gfx_rtpm = 1;
+
+               pm_runtime_enable(&gpDrmDevice->pdev->dev);
+               pm_runtime_set_active(&gpDrmDevice->pdev->dev);
+
+               pm_runtime_allow(&gpDrmDevice->pdev->dev);
+       }
+}
+#endif
+
+
+#if 1
+static int ospm_runtime_check_msvdx_hw_busy(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       int ret = 1;
+
+       if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
+               //printk(KERN_ALERT "%s VIDEO DEC HW is not on\n", __func__);
+               ret = -1;
+               goto out;
+       }
+
+       msvdx_priv->msvdx_hw_busy = REG_READ(0x20D0) & (0x1 << 9);
+       if (psb_check_msvdx_idle(dev)) {
+               //printk(KERN_ALERT "%s video decode hw busy\n", __func__);
+               ret = 1;
+       } else {
+               //printk(KERN_ALERT "%s video decode hw idle\n", __func__);
+               ret = 0;
+       }
+out:
+       return ret;
+}
+
+static int ospm_runtime_check_topaz_hw_busy(struct drm_device *dev)
+{
+       //struct drm_psb_private *dev_priv = dev->dev_private;
+       //struct topaz_private *topaz_priv = dev_priv->topaz_private;
+       int ret = 1;
+
+       if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+               //printk(KERN_ALERT "%s VIDEO ENC HW is not on\n", __func__);
+               ret = -1;
+               goto out;
+       }
+
+       //topaz_priv->topaz_hw_busy = REG_READ(0x20D0) & (0x1 << 11);
+
+       if (pnw_check_topaz_idle(dev)) {
+               //printk(KERN_ALERT "%s video encode hw busy %d\n", __func__,
+               //       topaz_priv->topaz_hw_busy);
+               ret = 1;
+       } else {
+               //printk(KERN_ALERT "%s video encode hw idle\n", __func__);
+               ret = 0;
+       }
+out:
+       return ret;
+}
+
+static int ospm_runtime_pm_msvdx_suspend(struct drm_device *dev)
+{
+       int ret = 0;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       //printk(KERN_ALERT "enter %s\n", __func__);
+
+       if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
+               //printk(KERN_ALERT "%s VIDEO DEC HW is not on\n", __func__);
+               goto out;
+       }
+
+       if (atomic_read(&g_videodec_access_count)) {
+               //printk(KERN_ALERT "%s videodec access count exit\n", __func__);
+               ret = -1;
+               goto out;
+       }
+
+       msvdx_priv->msvdx_hw_busy = REG_READ(0x20D0) & (0x1 << 9);
+       if (psb_check_msvdx_idle(dev)) {
+               //printk(KERN_ALERT "%s video decode hw busy exit\n", __func__);
+               ret = -2;
+               goto out;
+       }
+
+       MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERDOWN);
+       psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+       psb_msvdx_save_context(dev);
+       ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+       //printk(KERN_ALERT "%s done\n", __func__);
+out:
+       return ret;
+}
+
+static int ospm_runtime_pm_msvdx_resume(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       //printk(KERN_ALERT "ospm_runtime_pm_msvdx_resume\n");
+
+       MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERUP);
+
+       psb_msvdx_restore_context(dev);
+
+       return 0;
+}
+
+static int ospm_runtime_pm_topaz_suspend(struct drm_device *dev)
+{
+       int ret = 0;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
+       struct psb_video_ctx *pos, *n;
+       int encode_ctx = 0, encode_running = 0;
+
+       //printk(KERN_ALERT "enter %s\n", __func__);
+       list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+               int entrypoint = pos->ctx_type & 0xff;
+               if (entrypoint == VAEntrypointEncSlice ||
+                   entrypoint == VAEntrypointEncPicture) {
+                       encode_ctx = 1;
+                       break;
+               }
+       }
+
+       /* have encode context, but not started, or is just closed */
+       if (encode_ctx && dev_priv->topaz_ctx)
+               encode_running = 1;
+
+       if (encode_ctx)
+               PSB_DEBUG_PM("Topaz: has encode context, running=%d\n",
+                            encode_running);
+       else
+               PSB_DEBUG_PM("Topaz: no encode context\n");
+
+       if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+               //printk(KERN_ALERT "%s VIDEO ENC HW is not on\n", __func__);
+               goto out;
+       }
+
+       if (atomic_read(&g_videoenc_access_count)) {
+               //printk(KERN_ALERT "%s videoenc access count exit\n", __func__);
+               ret = -1;
+               goto out;
+       }
+
+       if (pnw_check_topaz_idle(dev)) {
+               //printk(KERN_ALERT "%s video encode hw busy exit\n", __func__);
+               ret = -2;
+               goto out;
+       }
+
+       psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+
+       if (encode_running) /* has encode session running */
+               pnw_topaz_save_mtx_state(gpDrmDevice);
+       PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERDOWN);
+
+       ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+       //printk(KERN_ALERT "%s done\n", __func__);
+out:
+       return ret;
+}
+
+static int ospm_runtime_pm_topaz_resume(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
+       struct psb_video_ctx *pos, *n;
+       int encode_ctx = 0, encode_running = 0;
+
+       //printk(KERN_ALERT "ospm_runtime_pm_topaz_resume\n");
+       list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+               int entrypoint = pos->ctx_type & 0xff;
+               if (entrypoint == VAEntrypointEncSlice ||
+                   entrypoint == VAEntrypointEncPicture) {
+                       encode_ctx = 1;
+                       break;
+               }
+       }
+
+       /* have encode context, but not started, or is just closed */
+       if (encode_ctx && dev_priv->topaz_ctx)
+               encode_running = 1;
+
+       if (encode_ctx)
+               PSB_DEBUG_PM("Topaz: has encode context, running=%d\n",
+                            encode_running);
+       else
+               PSB_DEBUG_PM("Topaz: no encode running\n");
+
+       if (encode_running) { /* has encode session running */
+               psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+               pnw_topaz_restore_mtx_state(gpDrmDevice);
+       }
+       PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERUP);
+
+       return 0;
+}
+#endif
+
+#ifdef FIX_OSPM_POWER_DOWN
+void ospm_apm_power_down_msvdx(struct drm_device *dev)
+{
+       return;
+       mutex_lock(&g_ospm_mutex);
+
+       if (atomic_read(&g_videodec_access_count))
+               goto out;
+       if (psb_check_msvdx_idle(dev))
+               goto out;
+
+       gbSuspendInProgress = true;
+       psb_msvdx_save_context(dev);
+#ifdef FIXME_MRST_VIDEO_DEC
+       ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+#endif
+       gbSuspendInProgress = false;
+out:
+       mutex_unlock(&g_ospm_mutex);
+       return;
+}
+
+void ospm_apm_power_down_topaz(struct drm_device *dev)
+{
+       return; /* todo for OSPM */
+
+       mutex_lock(&g_ospm_mutex);
+
+       if (atomic_read(&g_videoenc_access_count))
+               goto out;
+       if (lnc_check_topaz_idle(dev))
+               goto out;
+
+       gbSuspendInProgress = true;
+       lnc_topaz_save_mtx_state(dev);
+       ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+       gbSuspendInProgress = false;
+out:
+       mutex_unlock(&g_ospm_mutex);
+       return;
+}
+#else
+void ospm_apm_power_down_msvdx(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       mutex_lock(&g_ospm_mutex);
+       if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND))
+               goto out;
+
+       if (atomic_read(&g_videodec_access_count))
+               goto out;
+       if (psb_check_msvdx_idle(dev))
+               goto out;
+
+       gbSuspendInProgress = true;
+       psb_msvdx_save_context(dev);
+       ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+       gbSuspendInProgress = false;
+       MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERDOWN);
+out:
+       mutex_unlock(&g_ospm_mutex);
+       return;
+}
+
+void ospm_apm_power_down_topaz(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
+
+       mutex_lock(&g_ospm_mutex);
+
+       if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
+               goto out;
+       if (atomic_read(&g_videoenc_access_count))
+               goto out;
+       if (pnw_check_topaz_idle(dev))
+               goto out;
+
+       gbSuspendInProgress = true;
+       psb_irq_uninstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
+       pnw_topaz_save_mtx_state(gpDrmDevice);
+       PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERDOWN);
+
+       ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+       gbSuspendInProgress = false;
+out:
+       mutex_unlock(&g_ospm_mutex);
+       return;
+}
+#endif
+/*
+ * ospm_power_init
+ *
+ * Description: Initialize this ospm power management module
+ */
+void ospm_power_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private;
+
+       gpDrmDevice = dev;
+
+       dev_priv->apm_reg = MDFLD_MSG_READ32(PSB_PUNIT_PORT, PSB_APMBA);
+       dev_priv->ospm_base = MDFLD_MSG_READ32(PSB_PUNIT_PORT, PSB_OSPMBA);
+
+       dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
+       dev_priv->ospm_base &= 0xffff;
+
+       mutex_init(&g_ospm_mutex);
+       g_hw_power_status_mask = OSPM_ALL_ISLANDS;
+       atomic_set(&g_display_access_count, 0);
+       atomic_set(&g_graphics_access_count, 0);
+       atomic_set(&g_videoenc_access_count, 0);
+       atomic_set(&g_videodec_access_count, 0);
+
+#ifdef OSPM_STAT
+       dev_priv->graphics_state = PSB_PWR_STATE_ON;
+       dev_priv->gfx_last_mode_change = jiffies;
+       dev_priv->gfx_on_time = 0;
+       dev_priv->gfx_off_time = 0;
+#endif
+
+       spin_lock_init(&dev_priv->ospm_lock);
+
+#ifdef CONFIG_PM_RUNTIME
+       INIT_DELAYED_WORK(&dev_priv->rtpm_work, psb_runtimepm_wq_handler);
+#endif
+
+       return;
+}
+
+/*
+ * ospm_power_uninit
+ *
+ * Description: Uninitialize this ospm power management module
+ */
+void ospm_power_uninit(void)
+{
+       mutex_destroy(&g_ospm_mutex);
+       pm_runtime_forbid(&gpDrmDevice->pdev->dev);
+       pm_runtime_get_noresume(&gpDrmDevice->pdev->dev);
+}
+
+
+/*
+ * save_display_registers
+ *
+ * Description: We are going to suspend so save current display
+ * register state.
+ */
+static int save_display_registers(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct drm_crtc * crtc;
+       struct drm_connector * connector;
+
+       /* Display arbitration control + watermarks */
+       dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+       dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+       dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+       dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+       dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+       dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+       dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+       dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+       /*save crtc and output state*/
+       mutex_lock(&dev->mode_config.mutex);
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               if (drm_helper_crtc_in_use(crtc)) {
+                       crtc->funcs->save(crtc);
+               }
+       }
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               connector->funcs->save(connector);
+       }
+       mutex_unlock(&dev->mode_config.mutex);
+
+       /* Interrupt state */
+       /*
+        * Handled in psb_irq.c
+        */
+
+       return 0;
+}
+
+/*
+ * restore_display_registers
+ *
+ * Description: We are going to resume so restore display register state.
+ */
+static int restore_display_registers(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct drm_crtc * crtc;
+       struct drm_connector * connector;
+
+       /* Display arbitration + watermarks */
+       PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+       PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+       PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+       PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+       PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+       PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+       PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+       PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+       /*make sure VGA plane is off. it initializes to on after reset!*/
+       PSB_WVDC32(0x80000000, VGACNTRL);
+
+       mutex_lock(&dev->mode_config.mutex);
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               if (drm_helper_crtc_in_use(crtc))
+                       crtc->funcs->restore(crtc);
+       }
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               connector->funcs->restore(connector);
+       }
+       mutex_unlock(&dev->mode_config.mutex);
+
+       /*Interrupt state*/
+       /*
+        * Handled in psb_irq.c
+        */
+
+       return 0;
+}
+/*
+ * mdfld_save_display_registers
+ *
+ * Description: We are going to suspend so save current display
+ * register state.
+ *
+ * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
+ */
+static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int i;
+
+       /* regester */
+       u32 dpll_reg = MRST_DPLL_A;
+       u32 fp_reg = MRST_FPA0;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 htot_reg = HTOTAL_A;
+       u32 hblank_reg = HBLANK_A;
+       u32 hsync_reg = HSYNC_A;
+       u32 vtot_reg = VTOTAL_A;
+       u32 vblank_reg = VBLANK_A;
+       u32 vsync_reg = VSYNC_A;
+       u32 pipesrc_reg = PIPEASRC;
+       u32 dspstride_reg = DSPASTRIDE;
+       u32 dsplinoff_reg = DSPALINOFF;
+       u32 dsptileoff_reg = DSPATILEOFF;
+       u32 dspsize_reg = DSPASIZE;
+       u32 dsppos_reg = DSPAPOS;
+       u32 dspsurf_reg = DSPASURF;
+       u32 mipi_reg = MIPI;
+       u32 dspcntr_reg = DSPACNTR;
+       u32 dspstatus_reg = PIPEASTAT;
+       u32 palette_reg = PALETTE_A;
+
+       /* pointer to values */
+       u32 *dpll_val = &dev_priv->saveDPLL_A;
+       u32 *fp_val = &dev_priv->saveFPA0;
+       u32 *pipeconf_val = &dev_priv->savePIPEACONF;
+       u32 *htot_val = &dev_priv->saveHTOTAL_A;
+       u32 *hblank_val = &dev_priv->saveHBLANK_A;
+       u32 *hsync_val = &dev_priv->saveHSYNC_A;
+       u32 *vtot_val = &dev_priv->saveVTOTAL_A;
+       u32 *vblank_val = &dev_priv->saveVBLANK_A;
+       u32 *vsync_val = &dev_priv->saveVSYNC_A;
+       u32 *pipesrc_val = &dev_priv->savePIPEASRC;
+       u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
+       u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
+       u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
+       u32 *dspsize_val = &dev_priv->saveDSPASIZE;
+       u32 *dsppos_val = &dev_priv->saveDSPAPOS;
+       u32 *dspsurf_val = &dev_priv->saveDSPASURF;
+       u32 *mipi_val = &dev_priv->saveMIPI;
+       u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
+       u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
+       u32 *palette_val = dev_priv->save_palette_a;
+       PSB_DEBUG_ENTRY("\n");
+
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               /* regester */
+               dpll_reg = MDFLD_DPLL_B;
+               fp_reg = MDFLD_DPLL_DIV0;
+               pipeconf_reg = PIPEBCONF;
+               htot_reg = HTOTAL_B;
+               hblank_reg = HBLANK_B;
+               hsync_reg = HSYNC_B;
+               vtot_reg = VTOTAL_B;
+               vblank_reg = VBLANK_B;
+               vsync_reg = VSYNC_B;
+               pipesrc_reg = PIPEBSRC;
+               dspstride_reg = DSPBSTRIDE;
+               dsplinoff_reg = DSPBLINOFF;
+               dsptileoff_reg = DSPBTILEOFF;
+               dspsize_reg = DSPBSIZE;
+               dsppos_reg = DSPBPOS;
+               dspsurf_reg = DSPBSURF;
+               dspcntr_reg = DSPBCNTR;
+               dspstatus_reg = PIPEBSTAT;
+               palette_reg = PALETTE_B;
+
+               /* values */
+               dpll_val = &dev_priv->saveDPLL_B;
+               fp_val = &dev_priv->saveFPB0;
+               pipeconf_val = &dev_priv->savePIPEBCONF;
+               htot_val = &dev_priv->saveHTOTAL_B;
+               hblank_val = &dev_priv->saveHBLANK_B;
+               hsync_val = &dev_priv->saveHSYNC_B;
+               vtot_val = &dev_priv->saveVTOTAL_B;
+               vblank_val = &dev_priv->saveVBLANK_B;
+               vsync_val = &dev_priv->saveVSYNC_B;
+               pipesrc_val = &dev_priv->savePIPEBSRC;
+               dspstride_val = &dev_priv->saveDSPBSTRIDE;
+               dsplinoff_val = &dev_priv->saveDSPBLINOFF;
+               dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
+               dspsize_val = &dev_priv->saveDSPBSIZE;
+               dsppos_val = &dev_priv->saveDSPBPOS;
+               dspsurf_val = &dev_priv->saveDSPBSURF;
+               dspcntr_val = &dev_priv->saveDSPBCNTR;
+               dspstatus_val = &dev_priv->saveDSPBSTATUS;
+               palette_val = dev_priv->save_palette_b;
+               break;
+       case 2:
+               /* regester */
+               pipeconf_reg = PIPECCONF;
+               htot_reg = HTOTAL_C;
+               hblank_reg = HBLANK_C;
+               hsync_reg = HSYNC_C;
+               vtot_reg = VTOTAL_C;
+               vblank_reg = VBLANK_C;
+               vsync_reg = VSYNC_C;
+               pipesrc_reg = PIPECSRC;
+               dspstride_reg = DSPCSTRIDE;
+               dsplinoff_reg = DSPCLINOFF;
+               dsptileoff_reg = DSPCTILEOFF;
+               dspsize_reg = DSPCSIZE;
+               dsppos_reg = DSPCPOS;
+               dspsurf_reg = DSPCSURF;
+               mipi_reg = MIPI_C;
+               dspcntr_reg = DSPCCNTR;
+               dspstatus_reg = PIPECSTAT;
+               palette_reg = PALETTE_C;
+
+               /* pointer to values */
+               pipeconf_val = &dev_priv->savePIPECCONF;
+               htot_val = &dev_priv->saveHTOTAL_C;
+               hblank_val = &dev_priv->saveHBLANK_C;
+               hsync_val = &dev_priv->saveHSYNC_C;
+               vtot_val = &dev_priv->saveVTOTAL_C;
+               vblank_val = &dev_priv->saveVBLANK_C;
+               vsync_val = &dev_priv->saveVSYNC_C;
+               pipesrc_val = &dev_priv->savePIPECSRC;
+               dspstride_val = &dev_priv->saveDSPCSTRIDE;
+               dsplinoff_val = &dev_priv->saveDSPCLINOFF;
+               dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
+               dspsize_val = &dev_priv->saveDSPCSIZE;
+               dsppos_val = &dev_priv->saveDSPCPOS;
+               dspsurf_val = &dev_priv->saveDSPCSURF;
+               mipi_val = &dev_priv->saveMIPI_C;
+               dspcntr_val = &dev_priv->saveDSPCCNTR;
+               dspstatus_val = &dev_priv->saveDSPCSTATUS;
+               palette_val = dev_priv->save_palette_c;
+               break;
+       default:
+               DRM_ERROR("%s, invalid pipe number. \n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Pipe & plane A info */
+       *dpll_val = PSB_RVDC32(dpll_reg);
+       *fp_val = PSB_RVDC32(fp_reg);
+       *pipeconf_val = PSB_RVDC32(pipeconf_reg);
+       *htot_val = PSB_RVDC32(htot_reg);
+       *hblank_val = PSB_RVDC32(hblank_reg);
+       *hsync_val = PSB_RVDC32(hsync_reg);
+       *vtot_val = PSB_RVDC32(vtot_reg);
+       *vblank_val = PSB_RVDC32(vblank_reg);
+       *vsync_val = PSB_RVDC32(vsync_reg);
+       *pipesrc_val = PSB_RVDC32(pipesrc_reg);
+       *dspstride_val = PSB_RVDC32(dspstride_reg);
+       *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
+       *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
+       *dspsize_val = PSB_RVDC32(dspsize_reg);
+       *dsppos_val = PSB_RVDC32(dsppos_reg);
+       *dspsurf_val = PSB_RVDC32(dspsurf_reg);
+       *dspcntr_val = PSB_RVDC32(dspcntr_reg);
+       *dspstatus_val = PSB_RVDC32(dspstatus_reg);
+
+       /*save palette (gamma) */
+       for (i = 0; i < 256; i++)
+               palette_val[i] = PSB_RVDC32(palette_reg + (i << 2));
+
+       if (pipe == 1) {
+               dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+               dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+
+               dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
+               dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
+               return 0;
+       }
+
+       *mipi_val = PSB_RVDC32(mipi_reg);
+       return 0;
+}
+/*
+ * mdfld_save_cursor_overlay_registers
+ *
+ * Description: We are going to suspend so save current cursor and overlay display
+ * register state.
+ */
+static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       /*save cursor regs*/
+       dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+       dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+       dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+       dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
+       dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
+       dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
+
+       dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
+       dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
+       dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
+
+       /* HW overlay */
+       dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+       dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+       dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+       dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+       dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+       dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+       dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+       dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
+       dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
+       dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
+       dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
+       dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
+       dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
+       dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
+
+       return 0;
+}
+/*
+ * mdfld_restore_display_registers
+ *
+ * Description: We are going to resume so restore display register state.
+ *
+ * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
+ */
+static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
+{
+       //to get  panel out of ULPS mode.
+       u32 temp = 0;
+       u32 device_ready_reg = DEVICE_READY_REG;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct mdfld_dsi_dbi_output * dsi_output = dev_priv->dbi_output;
+       struct mdfld_dsi_config * dsi_config = NULL;
+       u32 i = 0;
+       u32 dpll = 0;
+       u32 timeout = 0;
+
+       /* regester */
+       u32 dpll_reg = MRST_DPLL_A;
+       u32 fp_reg = MRST_FPA0;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 htot_reg = HTOTAL_A;
+       u32 hblank_reg = HBLANK_A;
+       u32 hsync_reg = HSYNC_A;
+       u32 vtot_reg = VTOTAL_A;
+       u32 vblank_reg = VBLANK_A;
+       u32 vsync_reg = VSYNC_A;
+       u32 pipesrc_reg = PIPEASRC;
+       u32 dspstride_reg = DSPASTRIDE;
+       u32 dsplinoff_reg = DSPALINOFF;
+       u32 dsptileoff_reg = DSPATILEOFF;
+       u32 dspsize_reg = DSPASIZE;
+       u32 dsppos_reg = DSPAPOS;
+       u32 dspsurf_reg = DSPASURF;
+       u32 dspstatus_reg = PIPEASTAT;
+       u32 mipi_reg = MIPI;
+       u32 dspcntr_reg = DSPACNTR;
+       u32 palette_reg = PALETTE_A;
+
+       /* values */
+       u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
+       u32 fp_val = dev_priv->saveFPA0;
+       u32 pipeconf_val = dev_priv->savePIPEACONF;
+       u32 htot_val = dev_priv->saveHTOTAL_A;
+       u32 hblank_val = dev_priv->saveHBLANK_A;
+       u32 hsync_val = dev_priv->saveHSYNC_A;
+       u32 vtot_val = dev_priv->saveVTOTAL_A;
+       u32 vblank_val = dev_priv->saveVBLANK_A;
+       u32 vsync_val = dev_priv->saveVSYNC_A;
+       u32 pipesrc_val = dev_priv->savePIPEASRC;
+       u32 dspstride_val = dev_priv->saveDSPASTRIDE;
+       u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
+       u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
+       u32 dspsize_val = dev_priv->saveDSPASIZE;
+       u32 dsppos_val = dev_priv->saveDSPAPOS;
+       u32 dspsurf_val = dev_priv->saveDSPASURF;
+       u32 dspstatus_val = dev_priv->saveDSPASTATUS;
+       u32 mipi_val = dev_priv->saveMIPI;
+       u32 dspcntr_val = dev_priv->saveDSPACNTR;
+       u32 *palette_val = dev_priv->save_palette_a;
+       PSB_DEBUG_ENTRY("\n");
+
+       switch (pipe) {
+       case 0:
+               dsi_config = dev_priv->dsi_configs[0];
+               break;
+       case 1:
+               /* regester */
+               dpll_reg = MDFLD_DPLL_B;
+               fp_reg = MDFLD_DPLL_DIV0;
+               pipeconf_reg = PIPEBCONF;
+               htot_reg = HTOTAL_B;
+               hblank_reg = HBLANK_B;
+               hsync_reg = HSYNC_B;
+               vtot_reg = VTOTAL_B;
+               vblank_reg = VBLANK_B;
+               vsync_reg = VSYNC_B;
+               pipesrc_reg = PIPEBSRC;
+               dspstride_reg = DSPBSTRIDE;
+               dsplinoff_reg = DSPBLINOFF;
+               dsptileoff_reg = DSPBTILEOFF;
+               dspsize_reg = DSPBSIZE;
+               dsppos_reg = DSPBPOS;
+               dspsurf_reg = DSPBSURF;
+               dspcntr_reg = DSPBCNTR;
+               dspstatus_reg = PIPEBSTAT;
+               palette_reg = PALETTE_B;
+
+               /* values */
+               dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
+               fp_val = dev_priv->saveFPB0;
+               pipeconf_val = dev_priv->savePIPEBCONF;
+               htot_val = dev_priv->saveHTOTAL_B;
+               hblank_val = dev_priv->saveHBLANK_B;
+               hsync_val = dev_priv->saveHSYNC_B;
+               vtot_val = dev_priv->saveVTOTAL_B;
+               vblank_val = dev_priv->saveVBLANK_B;
+               vsync_val = dev_priv->saveVSYNC_B;
+               pipesrc_val = dev_priv->savePIPEBSRC;
+               dspstride_val = dev_priv->saveDSPBSTRIDE;
+               dsplinoff_val = dev_priv->saveDSPBLINOFF;
+               dsptileoff_val = dev_priv->saveDSPBTILEOFF;
+               dspsize_val = dev_priv->saveDSPBSIZE;
+               dsppos_val = dev_priv->saveDSPBPOS;
+               dspsurf_val = dev_priv->saveDSPBSURF;
+               dspcntr_val = dev_priv->saveDSPBCNTR;
+               dspstatus_val = dev_priv->saveDSPBSTATUS;
+               palette_val = dev_priv->save_palette_b;
+               break;
+       case 2:
+               dsi_output = dev_priv->dbi_output2;
+
+               /* regester */
+               pipeconf_reg = PIPECCONF;
+               htot_reg = HTOTAL_C;
+               hblank_reg = HBLANK_C;
+               hsync_reg = HSYNC_C;
+               vtot_reg = VTOTAL_C;
+               vblank_reg = VBLANK_C;
+               vsync_reg = VSYNC_C;
+               pipesrc_reg = PIPECSRC;
+               dspstride_reg = DSPCSTRIDE;
+               dsplinoff_reg = DSPCLINOFF;
+               dsptileoff_reg = DSPCTILEOFF;
+               dspsize_reg = DSPCSIZE;
+               dsppos_reg = DSPCPOS;
+               dspsurf_reg = DSPCSURF;
+               mipi_reg = MIPI_C;
+               dspcntr_reg = DSPCCNTR;
+               dspstatus_reg = PIPECSTAT;
+               palette_reg = PALETTE_C;
+
+               /* values */
+               pipeconf_val = dev_priv->savePIPECCONF;
+               htot_val = dev_priv->saveHTOTAL_C;
+               hblank_val = dev_priv->saveHBLANK_C;
+               hsync_val = dev_priv->saveHSYNC_C;
+               vtot_val = dev_priv->saveVTOTAL_C;
+               vblank_val = dev_priv->saveVBLANK_C;
+               vsync_val = dev_priv->saveVSYNC_C;
+               pipesrc_val = dev_priv->savePIPECSRC;
+               dspstride_val = dev_priv->saveDSPCSTRIDE;
+               dsplinoff_val = dev_priv->saveDSPCLINOFF;
+               dsptileoff_val = dev_priv->saveDSPCTILEOFF;
+               dspsize_val = dev_priv->saveDSPCSIZE;
+               dsppos_val = dev_priv->saveDSPCPOS;
+               dspsurf_val = dev_priv->saveDSPCSURF;
+               mipi_val = dev_priv->saveMIPI_C;
+               dspcntr_val = dev_priv->saveDSPCCNTR;
+               dspstatus_val = dev_priv->saveDSPCSTATUS;
+               palette_val = dev_priv->save_palette_c;
+
+               dsi_config = dev_priv->dsi_configs[1];
+               break;
+       default:
+               DRM_ERROR("%s, invalid pipe number. \n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /*make sure VGA plane is off. it initializes to on after reset!*/
+       PSB_WVDC32(0x80000000, VGACNTRL);
+
+       if (pipe == 1) {
+               PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
+               PSB_RVDC32(dpll_reg);
+
+               PSB_WVDC32(fp_val, fp_reg);
+       } else {
+
+               dpll = PSB_RVDC32(dpll_reg);
+
+               if (!(dpll & DPLL_VCO_ENABLE)) {
+
+                       /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+                       if (dpll & MDFLD_PWR_GATE_EN) {
+                               dpll &= ~MDFLD_PWR_GATE_EN;
+                               PSB_WVDC32(dpll, dpll_reg);
+                               /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                               udelay(500);
+                       }
+
+                       PSB_WVDC32(fp_val, fp_reg);
+                       PSB_WVDC32(dpll_val, dpll_reg);
+                       /* FIXME_MDFLD PO - change 500 to 1 after PO */
+                       udelay(500);
+
+                       dpll_val |= DPLL_VCO_ENABLE;
+                       PSB_WVDC32(dpll_val, dpll_reg);
+                       PSB_RVDC32(dpll_reg);
+
+                       /* wait for DSI PLL to lock */
+                       while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+                               udelay(150);
+                               timeout ++;
+                       }
+
+                       if (timeout == 20000) {
+                               DRM_ERROR("%s, can't lock DSIPLL. \n", __FUNCTION__);
+                               return -EINVAL;
+                       }
+               }
+       }
+       /* Restore mode */
+       PSB_WVDC32(htot_val, htot_reg);
+       PSB_WVDC32(hblank_val, hblank_reg);
+       PSB_WVDC32(hsync_val, hsync_reg);
+       PSB_WVDC32(vtot_val, vtot_reg);
+       PSB_WVDC32(vblank_val, vblank_reg);
+       PSB_WVDC32(vsync_val, vsync_reg);
+       PSB_WVDC32(pipesrc_val, pipesrc_reg);
+       PSB_WVDC32(dspstatus_val, dspstatus_reg);
+
+       /*set up the plane*/
+       PSB_WVDC32(dspstride_val, dspstride_reg);
+       PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
+       PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
+       PSB_WVDC32(dspsize_val, dspsize_reg);
+       PSB_WVDC32(dsppos_val, dsppos_reg);
+       PSB_WVDC32(dspsurf_val, dspsurf_reg);
+
+       if (pipe == 1) {
+               /* restore palette (gamma) */
+               /*DRM_UDELAY(50000); */
+               for (i = 0; i < 256; i++)
+                       PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
+
+               PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+               PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+
+               /*TODO: resume HDMI port */
+
+               /*TODO: resume pipe*/
+
+               /*enable the plane*/
+               PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg);
+
+               return 0;
+       }
+
+       /*set up pipe related registers*/
+       PSB_WVDC32(mipi_val, mipi_reg);
+
+       /*setup MIPI adapter + MIPI IP registers*/
+       if (dsi_config)
+               mdfld_dsi_controller_init(dsi_config, pipe);
+
+       if (in_atomic() || in_interrupt())
+               mdelay(20);
+       else
+               msleep(20);
+
+       /*enable the plane*/
+       PSB_WVDC32(dspcntr_val, dspcntr_reg);
+
+       if (in_atomic() || in_interrupt())
+               mdelay(20);
+       else
+               msleep(20);
+
+       /* LP Hold Release */
+       temp = REG_READ(mipi_reg);
+       temp |= LP_OUTPUT_HOLD_RELEASE;
+       REG_WRITE(mipi_reg, temp);
+       mdelay(1);
+
+
+       /* Set DSI host to exit from Utra Low Power State */
+       temp = REG_READ(device_ready_reg);
+       temp &= ~ULPS_MASK;
+       temp |= 0x3;
+       temp |= EXIT_ULPS_DEV_READY;
+       REG_WRITE(device_ready_reg, temp);
+       mdelay(1);
+
+       temp = REG_READ(device_ready_reg);
+       temp &= ~ULPS_MASK;
+       temp |= EXITING_ULPS;
+       REG_WRITE(device_ready_reg, temp);
+       mdelay(1);
+
+       /*enable the pipe*/
+       PSB_WVDC32(pipeconf_val, pipeconf_reg);
+
+       /* restore palette (gamma) */
+       /*DRM_UDELAY(50000); */
+       for (i = 0; i < 256; i++)
+               PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
+
+       return 0;
+}
+
+/*
+ * mdfld_restore_cursor_overlay_registers
+ *
+ * Description: We are going to resume so restore cursor and overlay register state.
+ */
+static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       /*Enable Cursor A*/
+       PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+       PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+       PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+       PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
+       PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
+       PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
+
+       PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
+       PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
+       PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
+
+       /* restore HW overlay */
+       PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+       PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
+
+       return 0;
+}
+
+/*
+ *  mdfld_save_display
+ *
+ * Description: Save display status before DPMS OFF for RuntimePM
+ */
+static void mdfld_save_display(struct drm_device *dev)
+{
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "ospm_save_display\n");
+#endif
+       mdfld_save_cursor_overlay_registers(dev);
+
+       mdfld_save_display_registers(dev, 0);
+
+       mdfld_save_display_registers(dev, 2);
+}
+/*
+ * powermgmt_suspend_display
+ *
+ * Description: Suspend the display hardware saving state and disabling
+ * as necessary.
+ */
+static void ospm_suspend_display(struct drm_device *dev)
+{
+       //to put panel into ULPS mode.
+       u32 temp = 0;
+       u32 device_ready_reg = DEVICE_READY_REG;
+       u32 mipi_reg = MIPI;
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "%s \n", __func__);
+#endif
+       if (!(g_hw_power_status_mask & OSPM_DISPLAY_ISLAND))
+               return;
+
+       mdfld_save_cursor_overlay_registers(dev);
+
+       mdfld_save_display_registers(dev, 0);
+       mdfld_save_display_registers(dev, 2);
+       mdfld_save_display_registers(dev, 1);
+
+       mdfld_disable_crtc(dev, 0);
+       mdfld_disable_crtc(dev, 2);
+       mdfld_disable_crtc(dev, 1);
+
+       /* Put the panel in ULPS mode for S0ix. */
+       temp = REG_READ(device_ready_reg);
+       temp &= ~ULPS_MASK;
+       temp |= ENTERING_ULPS;
+       REG_WRITE(device_ready_reg, temp);
+
+       //LP Hold
+       temp = REG_READ(mipi_reg);
+       temp &= ~LP_OUTPUT_HOLD;
+       REG_WRITE(mipi_reg, temp);
+       mdelay(1);
+
+       ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+}
+
+/*
+ * ospm_resume_display
+ *
+ * Description: Resume the display hardware restoring state and enabling
+ * as necessary.
+ */
+static void ospm_resume_display(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_gtt *pg = dev_priv->pg;
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "%s \n", __func__);
+#endif
+       if (g_hw_power_status_mask & OSPM_DISPLAY_ISLAND)
+               return;
+
+       /* turn on the display power island */
+       ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+
+       PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+       pci_write_config_word(pdev, PSB_GMCH_CTRL,
+                             pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+       /* Don't reinitialize the GTT as it is unnecessary.  The gtt is
+        * stored in memory so it will automatically be restored.  All
+        * we need to do is restore the PGETBL_CTL which we already do
+        * above.
+        */
+       /*psb_gtt_init(dev_priv->pg, 1);*/
+
+       mdfld_restore_display_registers(dev, 1);
+       mdfld_restore_display_registers(dev, 0);
+       mdfld_restore_display_registers(dev, 2);
+       mdfld_restore_cursor_overlay_registers(dev);
+}
+
+#if 1
+/*
+ * ospm_suspend_pci
+ *
+ * Description: Suspend the pci device saving state and disabling
+ * as necessary.
+ */
+static void ospm_suspend_pci(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int bsm, vbt;
+
+       if (gbSuspended)
+               return;
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "ospm_suspend_pci\n");
+#endif
+
+#ifdef CONFIG_MDFD_GL3
+       /* Power off GL3 after all GFX sub-systems are powered off. */
+       gl3_invalidate();
+       ospm_power_island_down(OSPM_GL3_CACHE_ISLAND);
+#endif
+
+       pci_save_state(pdev);
+       pci_read_config_dword(pdev, 0x5C, &bsm);
+       dev_priv->saveBSM = bsm;
+       pci_read_config_dword(pdev, 0xFC, &vbt);
+       dev_priv->saveVBT = vbt;
+       pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
+       pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
+
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+
+       gbSuspended = true;
+       gbgfxsuspended = true;
+}
+
+/*
+ * ospm_resume_pci
+ *
+ * Description: Resume the pci device restoring state and enabling
+ * as necessary.
+ */
+static bool ospm_resume_pci(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int ret = 0;
+
+       if (!gbSuspended)
+               return true;
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "ospm_resume_pci\n");
+#endif
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
+       pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
+       /* retoring MSI address and data in PCIx space */
+       pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
+       pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
+       ret = pci_enable_device(pdev);
+
+       if (ret != 0)
+               printk(KERN_ALERT "ospm_resume_pci: pci_enable_device failed: %d\n", ret);
+       else
+               gbSuspended = false;
+
+#ifdef CONFIG_MDFD_GL3
+       if (!ret) {
+               // Powerup GL3 - can be used by any GFX-sub-system.
+               ospm_power_island_up(OSPM_GL3_CACHE_ISLAND);
+
+       }
+#endif
+
+       return !gbSuspended;
+}
+#endif
+/*
+ * ospm_power_suspend
+ *
+ * Description: OSPM is telling our driver to suspend so save state
+ * and power down all hardware.
+ */
+int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       int ret = 0;
+       int graphics_access_count;
+       int videoenc_access_count;
+       int videodec_access_count;
+       int display_access_count;
+       bool suspend_pci = true;
+
+       if (gbSuspendInProgress || gbResumeInProgress) {
+#ifdef OSPM_GFX_DPK
+               printk(KERN_ALERT "OSPM_GFX_DPK: %s system BUSY \n", __func__);
+#endif
+               return  -EBUSY;
+       }
+
+       mutex_lock(&g_ospm_mutex);
+
+       if (!gbSuspended) {
+               graphics_access_count = atomic_read(&g_graphics_access_count);
+               videoenc_access_count = atomic_read(&g_videoenc_access_count);
+               videodec_access_count = atomic_read(&g_videodec_access_count);
+               display_access_count = atomic_read(&g_display_access_count);
+
+               if (graphics_access_count ||
+                   videoenc_access_count ||
+                   videodec_access_count ||
+                   display_access_count)
+                       ret = -EBUSY;
+
+               if (!ret) {
+                       gbSuspendInProgress = true;
+
+                       psb_irq_uninstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+                       ospm_suspend_display(gpDrmDevice);
+#if 1
+                       /* FIXME: video driver support for Linux Runtime PM */
+                       if (ospm_runtime_pm_msvdx_suspend(gpDrmDevice) != 0) {
+                               suspend_pci = false;
+                       }
+
+                       if (ospm_runtime_pm_topaz_suspend(gpDrmDevice) != 0) {
+                               suspend_pci = false;
+                       }
+
+#endif
+                       if (suspend_pci == true) {
+                               ospm_suspend_pci(pdev);
+                       }
+                       gbSuspendInProgress = false;
+               } else {
+                       printk(KERN_ALERT "ospm_power_suspend: device busy: graphics %d videoenc %d videodec %d display %d\n", graphics_access_count, videoenc_access_count, videodec_access_count, display_access_count);
+               }
+       }
+
+
+       mutex_unlock(&g_ospm_mutex);
+       return ret;
+}
+
+/*
+ * ospm_power_island_up
+ *
+ * Description: Restore power to the specified island(s) (powergating)
+ */
+void ospm_power_island_up(int hw_islands)
+{
+       u32 pwr_cnt = 0;
+       u32 pwr_sts = 0;
+       u32 pwr_mask = 0;
+       u32 cnt = 0;
+       unsigned long flags;
+       struct drm_psb_private *dev_priv = (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+       if (hw_islands & (OSPM_GRAPHICS_ISLAND | OSPM_VIDEO_ENC_ISLAND |
+                               OSPM_VIDEO_DEC_ISLAND | OSPM_GL3_CACHE_ISLAND |
+                               OSPM_ISP_ISLAND)) {
+               spin_lock_irqsave(&dev_priv->ospm_lock, flags);
+               pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
+
+               pwr_mask = 0;
+
+
+               if (hw_islands & OSPM_GRAPHICS_ISLAND) {
+                       pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
+                       pwr_mask |= PSB_PWRGT_GFX_MASK;
+#ifdef OSPM_STAT
+                       if (dev_priv->graphics_state == PSB_PWR_STATE_OFF) {
+                               dev_priv->gfx_off_time += (jiffies - dev_priv->gfx_last_mode_change) * 1000 / HZ;
+                               dev_priv->gfx_last_mode_change = jiffies;
+                               dev_priv->graphics_state = PSB_PWR_STATE_ON;
+                               dev_priv->gfx_on_cnt++;
+                       }
+#endif
+               }
+               if (hw_islands & OSPM_GL3_CACHE_ISLAND) {
+                       pwr_cnt &= ~PSB_PWRGT_GL3_MASK;
+                       pwr_mask |= PSB_PWRGT_GL3_MASK;
+               }
+               if (hw_islands & OSPM_VIDEO_ENC_ISLAND) {
+                       pwr_cnt &= ~PSB_PWRGT_VID_ENC_MASK;
+                       pwr_mask |= PSB_PWRGT_VID_ENC_MASK;
+               }
+               if (hw_islands & OSPM_VIDEO_DEC_ISLAND) {
+                       pwr_cnt &= ~PSB_PWRGT_VID_DEC_MASK;
+                       pwr_mask |= PSB_PWRGT_VID_DEC_MASK;
+               }
+               if (hw_islands & OSPM_ISP_ISLAND) {
+                       pwr_cnt &= ~PSB_PWRGT_ISP_MASK;
+                       pwr_mask |= PSB_PWRGT_ISP_MASK;
+               }
+
+               outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
+               spin_unlock_irqrestore(&dev_priv->ospm_lock, flags);
+
+               while (true) {
+                       pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
+                       if ((pwr_sts & pwr_mask) == 0)
+                               break;
+                       else
+                               udelay(10);
+                       cnt++;
+                       if (cnt > 1000) {
+                               printk(KERN_ALERT "%s: STUCK in INFINITE LOOP - failing on islands:0x%x\n", __func__, hw_islands);
+                               cnt = 0;
+                       }
+               }
+       }
+       if (hw_islands & OSPM_DISPLAY_ISLAND) {
+
+               pwr_mask = MDFLD_PWRGT_DISPLAY_CNTR;
+
+               spin_lock_irqsave(&dev_priv->ospm_lock, flags);
+               pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+               pwr_cnt &= ~pwr_mask;
+               outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
+               spin_unlock_irqrestore(&dev_priv->ospm_lock, flags);
+
+               pwr_mask = MDFLD_PWRGT_DISPLAY_STS_B0;
+
+               cnt = 0;
+               while (true) {
+                       pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+                       if ((pwr_sts & pwr_mask) == 0)
+                               break;
+                       else
+                               udelay(10);
+                       cnt++;
+                       if (cnt > 1000) {
+                               printk(KERN_ALERT "%s: STUCK in INFINITE LOOP - failing on DISPLAY \n", __func__);
+                               cnt = 0;
+                       }
+               }
+       }
+
+       g_hw_power_status_mask |= hw_islands;
+}
+
+/*
+ * ospm_power_resume
+ */
+int ospm_power_resume(struct pci_dev *pdev)
+{
+       if (gbSuspendInProgress || gbResumeInProgress) {
+#ifdef OSPM_GFX_DPK
+               printk(KERN_ALERT "OSPM_GFX_DPK: %s hw_island: Suspend || gbResumeInProgress!!!! \n", __func__);
+#endif
+               return 0;
+       }
+
+       mutex_lock(&g_ospm_mutex);
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "OSPM_GFX_DPK: ospm_power_resume \n");
+#endif
+
+       gbResumeInProgress = true;
+
+       ospm_resume_pci(pdev);
+
+       ospm_resume_display(gpDrmDevice->pdev);
+       psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+       psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+
+       gbResumeInProgress = false;
+
+       mutex_unlock(&g_ospm_mutex);
+
+       return 0;
+}
+
+
+/*
+ * ospm_power_island_down
+ *
+ * Description: Cut power to the specified island(s) (powergating)
+ */
+void ospm_power_island_down(int islands)
+{
+       u32 pwr_cnt = 0;
+       u32 pwr_mask = 0;
+       u32 pwr_sts = 0;
+       u32 cnt = 0;
+       unsigned long flags;
+       struct drm_psb_private *dev_priv = (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+       g_hw_power_status_mask &= ~islands;
+
+       if (islands & OSPM_GRAPHICS_ISLAND) {
+               pwr_cnt |= PSB_PWRGT_GFX_MASK;
+               pwr_mask |= PSB_PWRGT_GFX_MASK;
+#ifdef OSPM_STAT
+               if (dev_priv->graphics_state == PSB_PWR_STATE_ON) {
+                       dev_priv->gfx_on_time += (jiffies - dev_priv->gfx_last_mode_change) * 1000 / HZ;
+                       dev_priv->gfx_last_mode_change = jiffies;
+                       dev_priv->graphics_state = PSB_PWR_STATE_OFF;
+                       dev_priv->gfx_off_cnt++;
+               }
+#endif
+       }
+       if (islands & OSPM_GL3_CACHE_ISLAND) {
+               pwr_cnt |= PSB_PWRGT_GL3_MASK;
+               pwr_mask |= PSB_PWRGT_GL3_MASK;
+       }
+       if (islands & OSPM_VIDEO_ENC_ISLAND) {
+               pwr_cnt |= PSB_PWRGT_VID_ENC_MASK;
+               pwr_mask |= PSB_PWRGT_VID_ENC_MASK;
+       }
+       if (islands & OSPM_VIDEO_DEC_ISLAND) {
+               pwr_cnt |= PSB_PWRGT_VID_DEC_MASK;
+               pwr_mask |= PSB_PWRGT_VID_DEC_MASK;
+       }
+       if (islands & OSPM_ISP_ISLAND) {
+               pwr_cnt |= PSB_PWRGT_ISP_MASK;
+               pwr_mask |= PSB_PWRGT_ISP_MASK;
+       }
+       if (pwr_cnt) {
+               spin_lock_irqsave(&dev_priv->ospm_lock, flags);
+               pwr_cnt |= inl(dev_priv->apm_base);
+               outl(pwr_cnt, dev_priv->apm_base  + PSB_APM_CMD);
+               spin_unlock_irqrestore(&dev_priv->ospm_lock, flags);
+
+               while (true) {
+                       pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
+                       if ((pwr_sts & pwr_mask) == pwr_mask)
+                               break;
+                       else
+                               udelay(10);
+                       cnt++;
+                       if (cnt > 1000) {
+                               printk(KERN_ALERT "%s: STUCK in INFINITE LOOP - failing on islands:0x%x\n", __func__, islands);
+                               cnt = 0;
+                       }
+               }
+       }
+       if (islands & OSPM_DISPLAY_ISLAND) {
+
+               pwr_mask = MDFLD_PWRGT_DISPLAY_CNTR;
+
+               outl(pwr_mask, (dev_priv->ospm_base + PSB_PM_SSC));
+
+               pwr_mask = MDFLD_PWRGT_DISPLAY_STS_B0;
+
+               cnt = 0;
+               while (true) {
+                       pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+                       if ((pwr_sts & pwr_mask) == pwr_mask)
+                               break;
+                       else
+                               udelay(10);
+                       cnt++;
+                       if (cnt > 1000) {
+                               printk(KERN_ALERT "%s: STUCK in INFINITE LOOP - failing on Display island\n", __func__);
+                               cnt = 0;
+                       }
+               }
+       }
+}
+
+
+/*
+ * ospm_power_is_hw_on
+ *
+ * Description: do an instantaneous check for if the specified islands
+ * are on.  Only use this in cases where you know the g_state_change_mutex
+ * is already held such as in irq install/uninstall.  Otherwise, use
+ * ospm_power_using_hw_begin().
+ */
+bool ospm_power_is_hw_on(int hw_islands)
+{
+       return ((g_hw_power_status_mask & hw_islands) == hw_islands) ? true : false;
+}
+
+/*
+ * ospm_power_using_hw_begin
+ *
+ * Description: Notify PowerMgmt module that you will be accessing the
+ * specified island's hw so don't power it off.  If force_on is true,
+ * this will power on the specified island if it is off.
+ * Otherwise, this will return false and the caller is expected to not
+ * access the hw.
+ *
+ * NOTE *** If this is called from and interrupt handler or other atomic
+ * context, then it will return false if we are in the middle of a
+ * power state transition and the caller will be expected to handle that
+ * even if force_on is set to true.
+ */
+bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage)
+{
+       bool ret = true;
+       bool island_is_off = false;
+       bool b_atomic = (in_interrupt() || in_atomic());
+       bool locked = true;
+       struct pci_dev *pdev = gpDrmDevice->pdev;
+       IMG_UINT32 deviceID = 0;
+       bool force_on = usage ? true : false;
+
+#ifdef CONFIG_PM_RUNTIME
+       /* increment pm_runtime_refcount */
+       pm_runtime_get(&pdev->dev);
+#endif
+
+       /*quick path, not 100% race safe, but should be enough comapre to current other code in this file */
+       if (!force_on) {
+               if (hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask)) {
+#ifdef CONFIG_PM_RUNTIME
+                       /* decrement pm_runtime_refcount */
+                       pm_runtime_put(&pdev->dev);
+#endif
+                       return false;
+               } else {
+                       locked = false;
+                       goto increase_count;
+               }
+       }
+
+       if (!b_atomic)
+               mutex_lock(&g_ospm_mutex);
+
+       island_is_off = hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask);
+
+       if (b_atomic && (gbSuspendInProgress || gbResumeInProgress || gbSuspended) && force_on && island_is_off)
+               ret = false;
+
+       if (ret && island_is_off && !force_on)
+               ret = false;
+
+       if (ret && island_is_off && force_on) {
+               gbResumeInProgress = true;
+
+               ret = ospm_resume_pci(pdev);
+
+               if (ret) {
+                       switch (hw_island) {
+                       case OSPM_DISPLAY_ISLAND:
+                               deviceID = gui32MRSTDisplayDeviceID;
+                               ospm_resume_display(pdev);
+                               psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+                               psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+                               break;
+                       case OSPM_GRAPHICS_ISLAND:
+                               deviceID = gui32SGXDeviceID;
+                               ospm_power_island_up(OSPM_GRAPHICS_ISLAND);
+                               psb_irq_preinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+                               psb_irq_postinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+                               break;
+#if 1
+                       case OSPM_VIDEO_DEC_ISLAND:
+                               if (!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+                                       //printk(KERN_ALERT "%s power on display for video decode use\n", __func__);
+                                       deviceID = gui32MRSTDisplayDeviceID;
+                                       ospm_resume_display(pdev);
+                                       psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+                                       psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+                               } else {
+                                       //printk(KERN_ALERT "%s display is already on for video decode use\n", __func__);
+                               }
+
+                               if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
+                                       //printk(KERN_ALERT "%s power on video decode\n", __func__);
+                                       deviceID = gui32MRSTMSVDXDeviceID;
+                                       ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+                                       ospm_runtime_pm_msvdx_resume(gpDrmDevice);
+                                       psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+                                       psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+                               } else {
+                                       //printk(KERN_ALERT "%s video decode is already on\n", __func__);
+                               }
+
+                               break;
+                       case OSPM_VIDEO_ENC_ISLAND:
+                               if (!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+                                       //printk(KERN_ALERT "%s power on display for video encode\n", __func__);
+                                       deviceID = gui32MRSTDisplayDeviceID;
+                                       ospm_resume_display(pdev);
+                                       psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+                                       psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+                               } else {
+                                       //printk(KERN_ALERT "%s display is already on for video encode use\n", __func__);
+                               }
+
+                               if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+                                       //printk(KERN_ALERT "%s power on video encode\n", __func__);
+                                       deviceID = gui32MRSTTOPAZDeviceID;
+                                       ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+                                       ospm_runtime_pm_topaz_resume(gpDrmDevice);
+                                       psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+                                       psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+                               } else {
+                                       //printk(KERN_ALERT "%s video decode is already on\n", __func__);
+                               }
+#endif
+                               break;
+
+                       default:
+                               printk(KERN_ALERT "%s unknown island !!!! \n", __func__);
+                               break;
+                       }
+
+               }
+
+               if (!ret)
+                       printk(KERN_ALERT "ospm_power_using_hw_begin: forcing on %d failed\n", hw_island);
+
+               gbResumeInProgress = false;
+       }
+increase_count:
+       if (ret) {
+               switch (hw_island) {
+               case OSPM_GRAPHICS_ISLAND:
+                       atomic_inc(&g_graphics_access_count);
+                       break;
+               case OSPM_VIDEO_ENC_ISLAND:
+                       atomic_inc(&g_videoenc_access_count);
+                       break;
+               case OSPM_VIDEO_DEC_ISLAND:
+                       atomic_inc(&g_videodec_access_count);
+                       break;
+               case OSPM_DISPLAY_ISLAND:
+                       atomic_inc(&g_display_access_count);
+                       break;
+               }
+       } else {
+#ifdef CONFIG_PM_RUNTIME
+               /* decrement pm_runtime_refcount */
+               pm_runtime_put(&pdev->dev);
+#endif
+       }
+
+       if (!b_atomic && locked)
+               mutex_unlock(&g_ospm_mutex);
+
+       return ret;
+}
+
+
+/*
+ * ospm_power_using_hw_end
+ *
+ * Description: Notify PowerMgmt module that you are done accessing the
+ * specified island's hw so feel free to power it off.  Note that this
+ * function doesn't actually power off the islands.
+ */
+void ospm_power_using_hw_end(int hw_island)
+{
+       switch (hw_island) {
+       case OSPM_GRAPHICS_ISLAND:
+               atomic_dec(&g_graphics_access_count);
+               break;
+       case OSPM_VIDEO_ENC_ISLAND:
+               atomic_dec(&g_videoenc_access_count);
+               break;
+       case OSPM_VIDEO_DEC_ISLAND:
+               atomic_dec(&g_videodec_access_count);
+               break;
+       case OSPM_DISPLAY_ISLAND:
+               atomic_dec(&g_display_access_count);
+               break;
+       }
+
+       //decrement runtime pm ref count
+       pm_runtime_put(&gpDrmDevice->pdev->dev);
+
+       WARN_ON(atomic_read(&g_graphics_access_count) < 0);
+       WARN_ON(atomic_read(&g_videoenc_access_count) < 0);
+       WARN_ON(atomic_read(&g_videodec_access_count) < 0);
+       WARN_ON(atomic_read(&g_display_access_count) < 0);
+}
+
+int ospm_runtime_pm_allow(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       bool panel_on, panel_on2;
+
+       PSB_DEBUG_ENTRY("%s\n", __FUNCTION__);
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "OSPM_GFX_DPK: %s  \n", __func__);
+#endif
+       if (dev_priv->rpm_enabled)
+               return 0;
+
+       if (is_panel_vid_or_cmd(dev)) {
+               /*DPI panel*/
+               panel_on = dev_priv->dpi_panel_on;
+               panel_on2 = dev_priv->dpi_panel_on2;
+       } else {
+               /*DBI panel*/
+               panel_on = dev_priv->dbi_panel_on;
+               panel_on2 = dev_priv->dbi_panel_on2;
+       }
+
+       if (panel_on && panel_on2) {
+               pm_runtime_allow(&dev->pdev->dev);
+               dev_priv->rpm_enabled = 1;
+               DRM_INFO("Runtime PM enabled\n");
+       }
+
+       return 0;
+}
+
+void ospm_runtime_pm_forbid(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+
+       DRM_INFO("%s\n", __FUNCTION__);
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "OSPM_GFX_DPK: %s  \n", __func__);
+#endif
+
+       pm_runtime_forbid(&dev->pdev->dev);
+       dev_priv->rpm_enabled = 0;
+}
+
+int psb_runtime_suspend(struct device *dev)
+{
+       pm_message_t state;
+       int ret = 0;
+       state.event = 0;
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT "OSPM_GFX_DPK: %s \n", __func__);
+#endif
+        if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count)
+               || (gbdispstatus == true)
+               || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count)){
+#ifdef OSPM_GFX_DPK
+               printk(KERN_ALERT "OSPM_GFX_DPK: GFX: %d VEC: %d VED: %d DC: %d DSR: (N/A) \n", atomic_read(&g_graphics_access_count),
+                       atomic_read(&g_videoenc_access_count), atomic_read(&g_videodec_access_count), atomic_read(&g_display_access_count));
+#endif
+                return -EBUSY;
+        }
+        else
+               ret = ospm_power_suspend(gpDrmDevice->pdev, state);
+
+       return ret;
+}
+
+int psb_runtime_resume(struct device *dev)
+{
+       //Notify HDMI Audio sub-system about the resume.
+#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
+       struct drm_psb_private* dev_priv = gpDrmDevice->dev_private;
+
+       if (dev_priv->had_pvt_data)
+               dev_priv->had_interface->resume(dev_priv->had_pvt_data);
+#endif
+       /*Nop for GFX*/
+       return 0;
+}
+
+int psb_runtime_idle(struct device *dev)
+{
+#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
+       struct drm_psb_private* dev_priv = gpDrmDevice->dev_private;
+       int hdmi_audio_busy = 0;
+       pm_event_t hdmi_audio_event;
+#endif
+
+#if 1
+       int msvdx_hw_busy = 0;
+       int topaz_hw_busy = 0;
+
+       msvdx_hw_busy = ospm_runtime_check_msvdx_hw_busy(gpDrmDevice);
+       topaz_hw_busy = ospm_runtime_check_topaz_hw_busy(gpDrmDevice);
+#endif
+
+#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
+       if(dev_priv->had_pvt_data){
+               hdmi_audio_event.event = 0;
+               hdmi_audio_busy = dev_priv->had_interface->suspend(dev_priv->had_pvt_data, hdmi_audio_event);
+       }
+#endif
+       /*printk (KERN_ALERT "lvds:%d,mipi:%d\n", dev_priv->is_lvds_on, dev_priv->is_mipi_on);*/
+       if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count)
+               || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count)
+               || (gbdispstatus == true)
+#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
+               || hdmi_audio_busy
+#endif
+
+#if 1
+               || (msvdx_hw_busy == 1)
+               || (topaz_hw_busy == 1))
+#else
+               )
+#endif
+               return 1;
+               else
+                       return 0;
+}
+
diff --git a/drivers/staging/mrst/drv/psb_powermgmt.h b/drivers/staging/mrst/drv/psb_powermgmt.h
new file mode 100644 (file)
index 0000000..a645c9a
--- /dev/null
@@ -0,0 +1,113 @@
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ */
+#ifndef _PSB_POWERMGMT_H_
+#define _PSB_POWERMGMT_H_
+
+#include <linux/pci.h>
+#include <drm/drmP.h>
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif
+
+#define OSPM_GRAPHICS_ISLAND   0x1
+#define OSPM_VIDEO_ENC_ISLAND  0x2
+#define OSPM_VIDEO_DEC_ISLAND  0x4
+#define OSPM_DISPLAY_ISLAND    0x8
+#define OSPM_GL3_CACHE_ISLAND  0x10
+#define OSPM_ISP_ISLAND                0x20
+#define OSPM_ALL_ISLANDS       0x3f
+
+/* IPC message and command defines used to enable/disable mipi panel voltages */
+#define IPC_MSG_PANEL_ON_OFF    0xE9
+#define IPC_CMD_PANEL_ON        1
+#define IPC_CMD_PANEL_OFF       0
+
+typedef enum _UHBUsage
+{
+    OSPM_UHB_ONLY_IF_ON = 0,
+    OSPM_UHB_FORCE_POWER_ON,
+} UHBUsage;
+
+//extern int psb_check_msvdx_idle(struct drm_device *dev);
+//extern int lnc_check_topaz_idle(struct drm_device *dev);
+/* Use these functions to power down video HW for D0i3 purpose  */
+void ospm_apm_power_down_msvdx(struct drm_device *dev);
+void ospm_apm_power_down_topaz(struct drm_device *dev);
+
+void ospm_power_init(struct drm_device *dev);
+void ospm_power_uninit(void);
+
+
+/*
+ * OSPM will call these functions
+ */
+int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state);
+int ospm_power_resume(struct pci_dev *pdev);
+
+/*
+ * These are the functions the driver should use to wrap all hw access
+ * (i.e. register reads and writes)
+ */
+bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage);
+void ospm_power_using_hw_end(int hw_island);
+
+/*
+ * Use this function to do an instantaneous check for if the hw is on.
+ * Only use this in cases where you know the g_state_change_mutex
+ * is already held such as in irq install/uninstall and you need to
+ * prevent a deadlock situation.  Otherwise use ospm_power_using_hw_begin().
+ */
+bool ospm_power_is_hw_on(int hw_islands);
+
+/*
+ * Power up/down different hw component rails/islands
+ */
+void ospm_power_island_down(int hw_islands);
+void ospm_power_island_up(int hw_islands);
+/*
+ * GFX-Runtime PM callbacks
+ */
+int psb_runtime_suspend(struct device *dev);
+int psb_runtime_resume(struct device *dev);
+int psb_runtime_idle(struct device *dev);
+int ospm_runtime_pm_allow(struct drm_device * dev);
+void ospm_runtime_pm_forbid(struct drm_device * dev);
+
+#ifdef CONFIG_PM_RUNTIME
+void psb_runtimepm_wq_handler(struct work_struct *work);
+#endif
+
+extern struct drm_device *gpDrmDevice;
+extern bool gbgfxsuspended;
+extern bool gbdispstatus;
+#ifdef CONFIG_PM_RUNTIME
+extern int enable_gfx_rtpm;
+#endif
+
+#endif /*_PSB_POWERMGMT_H_*/
diff --git a/drivers/staging/mrst/drv/psb_pvr_glue.c b/drivers/staging/mrst/drv/psb_pvr_glue.c
new file mode 100644 (file)
index 0000000..bc5c86d
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "psb_pvr_glue.h"
+
+/**
+ * FIXME: should NOT use these file under env/linux directly
+ */
+#include "mm.h"
+
+int psb_get_meminfo_by_handle(IMG_HANDLE hKernelMemInfo,
+                               PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo)
+{
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+       PVRSRV_PER_PROCESS_DATA *psPerProc = IMG_NULL;
+       PVRSRV_ERROR eError;
+
+       psPerProc = PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                   (IMG_VOID *)&psKernelMemInfo,
+                                   hKernelMemInfo,
+                                   PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK) {
+               DRM_ERROR("Cannot find kernel meminfo for handle 0x%x\n",
+                         (IMG_UINT32)hKernelMemInfo);
+               return -EINVAL;
+       }
+
+       *ppsKernelMemInfo = psKernelMemInfo;
+
+       DRM_DEBUG("Got Kernel MemInfo for handle %p\n", hKernelMemInfo);
+
+       return 0;
+}
+
+IMG_UINT32 psb_get_tgid(void)
+{
+       return OSGetCurrentProcessIDKM();
+}
+
+int psb_get_pages_by_mem_handle(IMG_HANDLE hOSMemHandle, struct page ***pages)
+{
+       LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+       struct page **page_list;
+
+       if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES) {
+               DRM_ERROR("MemArea type is not LINUX_MEM_AREA_ALLOC_PAGES\n");
+               return -EINVAL;
+       }
+
+       page_list = psLinuxMemArea->uData.sPageList.pvPageList;
+       if (!page_list) {
+               DRM_DEBUG("Page List is NULL\n");
+               return -ENOMEM;
+       }
+
+       *pages = page_list;
+       return 0;
+}
diff --git a/drivers/staging/mrst/drv/psb_pvr_glue.h b/drivers/staging/mrst/drv/psb_pvr_glue.h
new file mode 100644 (file)
index 0000000..3c2ae45
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "psb_drv.h"
+#include "services_headers.h"
+
+extern int psb_get_meminfo_by_handle(IMG_HANDLE hKernelMemInfo,
+                               PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
+extern IMG_UINT32 psb_get_tgid(void);
+extern int psb_get_pages_by_mem_handle(IMG_HANDLE hOSMemHandle,
+                                       struct page ***pages);
diff --git a/drivers/staging/mrst/drv/psb_reg.h b/drivers/staging/mrst/drv/psb_reg.h
new file mode 100644 (file)
index 0000000..89a05fa
--- /dev/null
@@ -0,0 +1,588 @@
+/**************************************************************************
+ *
+ * Copyright (c) (2005-2007) Imagination Technologies Limited.
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA..
+ *
+ **************************************************************************/
+
+#ifndef _PSB_REG_H_
+#define _PSB_REG_H_
+
+#define PSB_CR_CLKGATECTL                0x0000
+#define _PSB_C_CLKGATECTL_AUTO_MAN_REG   (1 << 24)
+#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20)
+#define _PSB_C_CLKGATECTL_USE_CLKG_MASK  (0x3 << 20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK  (0x3 << 16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT  (12)
+#define _PSB_C_CLKGATECTL_TA_CLKG_MASK   (0x3 << 12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK  (0x3 << 8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK  (0x3 << 4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT  (0)
+#define _PSB_C_CLKGATECTL_2D_CLKG_MASK   (0x3 << 0)
+#define _PSB_C_CLKGATECTL_CLKG_ENABLED   (0)
+#define _PSB_C_CLKGATECTL_CLKG_DISABLED  (1)
+#define _PSB_C_CLKGATECTL_CLKG_AUTO      (2)
+
+#define PSB_CR_CORE_ID                   0x0010
+#define _PSB_CC_ID_ID_SHIFT              (16)
+#define _PSB_CC_ID_ID_MASK               (0xFFFF << 16)
+#define _PSB_CC_ID_CONFIG_SHIFT          (0)
+#define _PSB_CC_ID_CONFIG_MASK           (0xFFFF << 0)
+
+#define PSB_CR_CORE_REVISION               0x0014
+#define _PSB_CC_REVISION_DESIGNER_SHIFT    (24)
+#define _PSB_CC_REVISION_DESIGNER_MASK     (0xFF << 24)
+#define _PSB_CC_REVISION_MAJOR_SHIFT       (16)
+#define _PSB_CC_REVISION_MAJOR_MASK        (0xFF << 16)
+#define _PSB_CC_REVISION_MINOR_SHIFT       (8)
+#define _PSB_CC_REVISION_MINOR_MASK        (0xFF << 8)
+#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0)
+#define _PSB_CC_REVISION_MAINTENANCE_MASK  (0xFF << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD1       0x0018
+
+#define PSB_CR_SOFT_RESET                0x0080
+#define _PSB_CS_RESET_TSP_RESET          (1 << 6)
+#define _PSB_CS_RESET_ISP_RESET          (1 << 5)
+#define _PSB_CS_RESET_USE_RESET          (1 << 4)
+#define _PSB_CS_RESET_TA_RESET           (1 << 3)
+#define _PSB_CS_RESET_DPM_RESET          (1 << 2)
+#define _PSB_CS_RESET_TWOD_RESET         (1 << 1)
+#define _PSB_CS_RESET_BIF_RESET          (1 << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD2       0x001C
+
+#define PSB_CR_EVENT_HOST_ENABLE2        0x0110
+
+#define PSB_CR_EVENT_STATUS2             0x0118
+
+#define PSB_CR_EVENT_HOST_CLEAR2         0x0114
+#define _PSB_CE2_BIF_REQUESTER_FAULT     (1 << 4)
+
+#define PSB_CR_EVENT_STATUS              0x012C
+
+#define PSB_CR_EVENT_HOST_ENABLE         0x0130
+
+#define PSB_CR_EVENT_HOST_CLEAR          0x0134
+#define _PSB_CE_MASTER_INTERRUPT         (1 << 31)
+#define _PSB_CE_TA_DPM_FAULT             (1 << 28)
+#define _PSB_CE_TWOD_COMPLETE            (1 << 27)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS    (1 << 25)
+#define _PSB_CE_DPM_TA_MEM_FREE          (1 << 24)
+#define _PSB_CE_PIXELBE_END_RENDER       (1 << 18)
+#define _PSB_CE_SW_EVENT                 (1 << 14)
+#define _PSB_CE_TA_FINISHED              (1 << 13)
+#define _PSB_CE_TA_TERMINATE             (1 << 12)
+#define _PSB_CE_DPM_REACHED_MEM_THRESH   (1 << 3)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL    (1 << 2)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_MT     (1 << 1)
+#define _PSB_CE_DPM_3D_MEM_FREE          (1 << 0)
+
+
+#define PSB_USE_OFFSET_MASK              0x0007FFFF
+#define PSB_USE_OFFSET_SIZE              (PSB_USE_OFFSET_MASK + 1)
+#define PSB_CR_USE_CODE_BASE0            0x0A0C
+#define PSB_CR_USE_CODE_BASE1            0x0A10
+#define PSB_CR_USE_CODE_BASE2            0x0A14
+#define PSB_CR_USE_CODE_BASE3            0x0A18
+#define PSB_CR_USE_CODE_BASE4            0x0A1C
+#define PSB_CR_USE_CODE_BASE5            0x0A20
+#define PSB_CR_USE_CODE_BASE6            0x0A24
+#define PSB_CR_USE_CODE_BASE7            0x0A28
+#define PSB_CR_USE_CODE_BASE8            0x0A2C
+#define PSB_CR_USE_CODE_BASE9            0x0A30
+#define PSB_CR_USE_CODE_BASE10           0x0A34
+#define PSB_CR_USE_CODE_BASE11           0x0A38
+#define PSB_CR_USE_CODE_BASE12           0x0A3C
+#define PSB_CR_USE_CODE_BASE13           0x0A40
+#define PSB_CR_USE_CODE_BASE14           0x0A44
+#define PSB_CR_USE_CODE_BASE15           0x0A48
+#define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2))
+#define _PSB_CUC_BASE_DM_SHIFT           (25)
+#define _PSB_CUC_BASE_DM_MASK            (0x3 << 25)
+#define _PSB_CUC_BASE_ADDR_SHIFT         (0)   /* 1024-bit aligned address? */
+#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT    (7)
+#define _PSB_CUC_BASE_ADDR_MASK          (0x1FFFFFF << 0)
+#define _PSB_CUC_DM_VERTEX              (0)
+#define _PSB_CUC_DM_PIXEL               (1)
+#define _PSB_CUC_DM_RESERVED            (2)
+#define _PSB_CUC_DM_EDM                         (3)
+
+#define PSB_CR_PDS_EXEC_BASE             0x0AB8
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20)  /* 1MB aligned address */
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20)
+
+#define PSB_CR_EVENT_KICKER              0x0AC4
+#define _PSB_CE_KICKER_ADDRESS_SHIFT     (4)   /* 128-bit aligned address */
+
+#define PSB_CR_EVENT_KICK                0x0AC8
+#define _PSB_CE_KICK_NOW                 (1 << 0)
+
+
+#define PSB_CR_BIF_DIR_LIST_BASE1        0x0C38
+
+#define PSB_CR_BIF_CTRL                  0x0C00
+#define _PSB_CB_CTRL_CLEAR_FAULT         (1 << 4)
+#define _PSB_CB_CTRL_INVALDC             (1 << 3)
+#define _PSB_CB_CTRL_FLUSH               (1 << 2)
+
+#define PSB_CR_BIF_INT_STAT              0x0C04
+
+#define PSB_CR_BIF_FAULT                 0x0C08
+#define _PSB_CBI_STAT_PF_N_RW            (1 << 14)
+#define _PSB_CBI_STAT_FAULT_SHIFT        (0)
+#define _PSB_CBI_STAT_FAULT_MASK         (0x3FFF << 0)
+#define _PSB_CBI_STAT_FAULT_CACHE        (1 << 1)
+#define _PSB_CBI_STAT_FAULT_TA           (1 << 2)
+#define _PSB_CBI_STAT_FAULT_VDM          (1 << 3)
+#define _PSB_CBI_STAT_FAULT_2D           (1 << 4)
+#define _PSB_CBI_STAT_FAULT_PBE          (1 << 5)
+#define _PSB_CBI_STAT_FAULT_TSP          (1 << 6)
+#define _PSB_CBI_STAT_FAULT_ISP          (1 << 7)
+#define _PSB_CBI_STAT_FAULT_USSEPDS      (1 << 8)
+#define _PSB_CBI_STAT_FAULT_HOST         (1 << 9)
+
+#define PSB_CR_BIF_BANK0                 0x0C78
+
+#define PSB_CR_BIF_BANK1                 0x0C7C
+
+#define PSB_CR_BIF_DIR_LIST_BASE0        0x0C84
+
+#define PSB_CR_BIF_TWOD_REQ_BASE         0x0C88
+#define PSB_CR_BIF_3D_REQ_BASE           0x0CAC
+
+#define PSB_CR_2D_SOCIF                  0x0E18
+#define _PSB_C2_SOCIF_FREESPACE_SHIFT    (0)
+#define _PSB_C2_SOCIF_FREESPACE_MASK     (0xFF << 0)
+#define _PSB_C2_SOCIF_EMPTY              (0x80 << 0)
+
+#define PSB_CR_2D_BLIT_STATUS            0x0E04
+#define _PSB_C2B_STATUS_BUSY             (1 << 24)
+#define _PSB_C2B_STATUS_COMPLETE_SHIFT   (0)
+#define _PSB_C2B_STATUS_COMPLETE_MASK    (0xFFFFFF << 0)
+
+/*
+ * 2D defs.
+ */
+
+/*
+ * 2D Slave Port Data : Block Header's Object Type
+ */
+
+#define        PSB_2D_CLIP_BH                   (0x00000000)
+#define        PSB_2D_PAT_BH                    (0x10000000)
+#define        PSB_2D_CTRL_BH                   (0x20000000)
+#define        PSB_2D_SRC_OFF_BH                (0x30000000)
+#define        PSB_2D_MASK_OFF_BH               (0x40000000)
+#define        PSB_2D_RESERVED1_BH              (0x50000000)
+#define        PSB_2D_RESERVED2_BH              (0x60000000)
+#define        PSB_2D_FENCE_BH                  (0x70000000)
+#define        PSB_2D_BLIT_BH                   (0x80000000)
+#define        PSB_2D_SRC_SURF_BH               (0x90000000)
+#define        PSB_2D_DST_SURF_BH               (0xA0000000)
+#define        PSB_2D_PAT_SURF_BH               (0xB0000000)
+#define        PSB_2D_SRC_PAL_BH                (0xC0000000)
+#define        PSB_2D_PAT_PAL_BH                (0xD0000000)
+#define        PSB_2D_MASK_SURF_BH              (0xE0000000)
+#define        PSB_2D_FLUSH_BH                  (0xF0000000)
+
+/*
+ * Clip Definition block (PSB_2D_CLIP_BH)
+ */
+#define PSB_2D_CLIPCOUNT_MAX             (1)
+#define PSB_2D_CLIPCOUNT_MASK            (0x00000000)
+#define PSB_2D_CLIPCOUNT_CLRMASK         (0xFFFFFFFF)
+#define PSB_2D_CLIPCOUNT_SHIFT           (0)
+/* clip rectangle min & max */
+#define PSB_2D_CLIP_XMAX_MASK            (0x00FFF000)
+#define PSB_2D_CLIP_XMAX_CLRMASK         (0xFF000FFF)
+#define PSB_2D_CLIP_XMAX_SHIFT           (12)
+#define PSB_2D_CLIP_XMIN_MASK            (0x00000FFF)
+#define PSB_2D_CLIP_XMIN_CLRMASK         (0x00FFF000)
+#define PSB_2D_CLIP_XMIN_SHIFT           (0)
+/* clip rectangle offset */
+#define PSB_2D_CLIP_YMAX_MASK            (0x00FFF000)
+#define PSB_2D_CLIP_YMAX_CLRMASK         (0xFF000FFF)
+#define PSB_2D_CLIP_YMAX_SHIFT           (12)
+#define PSB_2D_CLIP_YMIN_MASK            (0x00000FFF)
+#define PSB_2D_CLIP_YMIN_CLRMASK         (0x00FFF000)
+#define PSB_2D_CLIP_YMIN_SHIFT           (0)
+
+/*
+ * Pattern Control (PSB_2D_PAT_BH)
+ */
+#define PSB_2D_PAT_HEIGHT_MASK           (0x0000001F)
+#define PSB_2D_PAT_HEIGHT_SHIFT          (0)
+#define PSB_2D_PAT_WIDTH_MASK            (0x000003E0)
+#define PSB_2D_PAT_WIDTH_SHIFT           (5)
+#define PSB_2D_PAT_YSTART_MASK           (0x00007C00)
+#define PSB_2D_PAT_YSTART_SHIFT          (10)
+#define PSB_2D_PAT_XSTART_MASK           (0x000F8000)
+#define PSB_2D_PAT_XSTART_SHIFT          (15)
+
+/*
+ * 2D Control block (PSB_2D_CTRL_BH)
+ */
+/* Present Flags */
+#define PSB_2D_SRCCK_CTRL                (0x00000001)
+#define PSB_2D_DSTCK_CTRL                (0x00000002)
+#define PSB_2D_ALPHA_CTRL                (0x00000004)
+/* Colour Key Colour (SRC/DST)*/
+#define PSB_2D_CK_COL_MASK               (0xFFFFFFFF)
+#define PSB_2D_CK_COL_CLRMASK            (0x00000000)
+#define PSB_2D_CK_COL_SHIFT              (0)
+/* Colour Key Mask (SRC/DST)*/
+#define PSB_2D_CK_MASK_MASK              (0xFFFFFFFF)
+#define PSB_2D_CK_MASK_CLRMASK           (0x00000000)
+#define PSB_2D_CK_MASK_SHIFT             (0)
+/* Alpha Control (Alpha/RGB)*/
+#define PSB_2D_GBLALPHA_MASK             (0x000FF000)
+#define PSB_2D_GBLALPHA_CLRMASK          (0xFFF00FFF)
+#define PSB_2D_GBLALPHA_SHIFT            (12)
+#define PSB_2D_SRCALPHA_OP_MASK          (0x00700000)
+#define PSB_2D_SRCALPHA_OP_CLRMASK       (0xFF8FFFFF)
+#define PSB_2D_SRCALPHA_OP_SHIFT         (20)
+#define PSB_2D_SRCALPHA_OP_ONE           (0x00000000)
+#define PSB_2D_SRCALPHA_OP_SRC           (0x00100000)
+#define PSB_2D_SRCALPHA_OP_DST           (0x00200000)
+#define PSB_2D_SRCALPHA_OP_SG            (0x00300000)
+#define PSB_2D_SRCALPHA_OP_DG            (0x00400000)
+#define PSB_2D_SRCALPHA_OP_GBL           (0x00500000)
+#define PSB_2D_SRCALPHA_OP_ZERO          (0x00600000)
+#define PSB_2D_SRCALPHA_INVERT           (0x00800000)
+#define PSB_2D_SRCALPHA_INVERT_CLR       (0xFF7FFFFF)
+#define PSB_2D_DSTALPHA_OP_MASK          (0x07000000)
+#define PSB_2D_DSTALPHA_OP_CLRMASK       (0xF8FFFFFF)
+#define PSB_2D_DSTALPHA_OP_SHIFT         (24)
+#define PSB_2D_DSTALPHA_OP_ONE           (0x00000000)
+#define PSB_2D_DSTALPHA_OP_SRC           (0x01000000)
+#define PSB_2D_DSTALPHA_OP_DST           (0x02000000)
+#define PSB_2D_DSTALPHA_OP_SG            (0x03000000)
+#define PSB_2D_DSTALPHA_OP_DG            (0x04000000)
+#define PSB_2D_DSTALPHA_OP_GBL           (0x05000000)
+#define PSB_2D_DSTALPHA_OP_ZERO          (0x06000000)
+#define PSB_2D_DSTALPHA_INVERT           (0x08000000)
+#define PSB_2D_DSTALPHA_INVERT_CLR       (0xF7FFFFFF)
+
+#define PSB_2D_PRE_MULTIPLICATION_ENABLE  (0x10000000)
+#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF)
+#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE   (0x20000000)
+#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK  (0xDFFFFFFF)
+
+/*
+ *Source Offset (PSB_2D_SRC_OFF_BH)
+ */
+#define PSB_2D_SRCOFF_XSTART_MASK        ((0x00000FFF) << 12)
+#define PSB_2D_SRCOFF_XSTART_SHIFT       (12)
+#define PSB_2D_SRCOFF_YSTART_MASK        (0x00000FFF)
+#define PSB_2D_SRCOFF_YSTART_SHIFT       (0)
+
+/*
+ * Mask Offset (PSB_2D_MASK_OFF_BH)
+ */
+#define PSB_2D_MASKOFF_XSTART_MASK       ((0x00000FFF) << 12)
+#define PSB_2D_MASKOFF_XSTART_SHIFT      (12)
+#define PSB_2D_MASKOFF_YSTART_MASK       (0x00000FFF)
+#define PSB_2D_MASKOFF_YSTART_SHIFT      (0)
+
+/*
+ * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored
+ */
+
+/*
+ *Blit Rectangle (PSB_2D_BLIT_BH)
+ */
+
+#define PSB_2D_ROT_MASK                  (3<<25)
+#define PSB_2D_ROT_CLRMASK               (~PSB_2D_ROT_MASK)
+#define PSB_2D_ROT_NONE                  (0<<25)
+#define PSB_2D_ROT_90DEGS                (1<<25)
+#define PSB_2D_ROT_180DEGS               (2<<25)
+#define PSB_2D_ROT_270DEGS               (3<<25)
+
+#define PSB_2D_COPYORDER_MASK            (3<<23)
+#define PSB_2D_COPYORDER_CLRMASK         (~PSB_2D_COPYORDER_MASK)
+#define PSB_2D_COPYORDER_TL2BR           (0<<23)
+#define PSB_2D_COPYORDER_BR2TL           (1<<23)
+#define PSB_2D_COPYORDER_TR2BL           (2<<23)
+#define PSB_2D_COPYORDER_BL2TR           (3<<23)
+
+#define PSB_2D_DSTCK_CLRMASK             (0xFF9FFFFF)
+#define PSB_2D_DSTCK_DISABLE             (0x00000000)
+#define PSB_2D_DSTCK_PASS                (0x00200000)
+#define PSB_2D_DSTCK_REJECT              (0x00400000)
+
+#define PSB_2D_SRCCK_CLRMASK             (0xFFE7FFFF)
+#define PSB_2D_SRCCK_DISABLE             (0x00000000)
+#define PSB_2D_SRCCK_PASS                (0x00080000)
+#define PSB_2D_SRCCK_REJECT              (0x00100000)
+
+#define PSB_2D_CLIP_ENABLE               (0x00040000)
+
+#define PSB_2D_ALPHA_ENABLE              (0x00020000)
+
+#define PSB_2D_PAT_CLRMASK               (0xFFFEFFFF)
+#define PSB_2D_PAT_MASK                  (0x00010000)
+#define PSB_2D_USE_PAT                   (0x00010000)
+#define PSB_2D_USE_FILL                  (0x00000000)
+/*
+ * Tungsten Graphics note on rop codes: If rop A and rop B are
+ * identical, the mask surface will not be read and need not be
+ * set up.
+ */
+
+#define PSB_2D_ROP3B_MASK                (0x0000FF00)
+#define PSB_2D_ROP3B_CLRMASK             (0xFFFF00FF)
+#define PSB_2D_ROP3B_SHIFT               (8)
+/* rop code A */
+#define PSB_2D_ROP3A_MASK                (0x000000FF)
+#define PSB_2D_ROP3A_CLRMASK             (0xFFFFFF00)
+#define PSB_2D_ROP3A_SHIFT               (0)
+
+#define PSB_2D_ROP4_MASK                 (0x0000FFFF)
+/*
+ *     DWORD0: (Only pass if Pattern control == Use Fill Colour)
+ *     Fill Colour RGBA8888
+ */
+#define PSB_2D_FILLCOLOUR_MASK           (0xFFFFFFFF)
+#define PSB_2D_FILLCOLOUR_SHIFT          (0)
+/*
+ *     DWORD1: (Always Present)
+ *     X Start (Dest)
+ *     Y Start (Dest)
+ */
+#define PSB_2D_DST_XSTART_MASK           (0x00FFF000)
+#define PSB_2D_DST_XSTART_CLRMASK        (0xFF000FFF)
+#define PSB_2D_DST_XSTART_SHIFT          (12)
+#define PSB_2D_DST_YSTART_MASK           (0x00000FFF)
+#define PSB_2D_DST_YSTART_CLRMASK        (0xFFFFF000)
+#define PSB_2D_DST_YSTART_SHIFT          (0)
+/*
+ *     DWORD2: (Always Present)
+ *     X Size (Dest)
+ *     Y Size (Dest)
+ */
+#define PSB_2D_DST_XSIZE_MASK            (0x00FFF000)
+#define PSB_2D_DST_XSIZE_CLRMASK         (0xFF000FFF)
+#define PSB_2D_DST_XSIZE_SHIFT           (12)
+#define PSB_2D_DST_YSIZE_MASK            (0x00000FFF)
+#define PSB_2D_DST_YSIZE_CLRMASK         (0xFFFFF000)
+#define PSB_2D_DST_YSIZE_SHIFT           (0)
+
+/*
+ * Source Surface (PSB_2D_SRC_SURF_BH)
+ */
+/*
+ *      WORD 0
+ */
+
+#define PSB_2D_SRC_FORMAT_MASK           (0x00078000)
+#define PSB_2D_SRC_1_PAL                 (0x00000000)
+#define PSB_2D_SRC_2_PAL                 (0x00008000)
+#define PSB_2D_SRC_4_PAL                 (0x00010000)
+#define PSB_2D_SRC_8_PAL                 (0x00018000)
+#define PSB_2D_SRC_8_ALPHA               (0x00020000)
+#define PSB_2D_SRC_4_ALPHA               (0x00028000)
+#define PSB_2D_SRC_332RGB                (0x00030000)
+#define PSB_2D_SRC_4444ARGB              (0x00038000)
+#define PSB_2D_SRC_555RGB                (0x00040000)
+#define PSB_2D_SRC_1555ARGB              (0x00048000)
+#define PSB_2D_SRC_565RGB                (0x00050000)
+#define PSB_2D_SRC_0888ARGB              (0x00058000)
+#define PSB_2D_SRC_8888ARGB              (0x00060000)
+#define PSB_2D_SRC_8888UYVY              (0x00068000)
+#define PSB_2D_SRC_RESERVED              (0x00070000)
+#define PSB_2D_SRC_1555ARGB_LOOKUP       (0x00078000)
+
+
+#define PSB_2D_SRC_STRIDE_MASK           (0x00007FFF)
+#define PSB_2D_SRC_STRIDE_CLRMASK        (0xFFFF8000)
+#define PSB_2D_SRC_STRIDE_SHIFT          (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_SRC_ADDR_MASK             (0x0FFFFFFC)
+#define PSB_2D_SRC_ADDR_CLRMASK          (0x00000003)
+#define PSB_2D_SRC_ADDR_SHIFT            (2)
+#define PSB_2D_SRC_ADDR_ALIGNSHIFT       (2)
+
+/*
+ * Pattern Surface (PSB_2D_PAT_SURF_BH)
+ */
+/*
+ *  WORD 0
+ */
+
+#define PSB_2D_PAT_FORMAT_MASK           (0x00078000)
+#define PSB_2D_PAT_1_PAL                 (0x00000000)
+#define PSB_2D_PAT_2_PAL                 (0x00008000)
+#define PSB_2D_PAT_4_PAL                 (0x00010000)
+#define PSB_2D_PAT_8_PAL                 (0x00018000)
+#define PSB_2D_PAT_8_ALPHA               (0x00020000)
+#define PSB_2D_PAT_4_ALPHA               (0x00028000)
+#define PSB_2D_PAT_332RGB                (0x00030000)
+#define PSB_2D_PAT_4444ARGB              (0x00038000)
+#define PSB_2D_PAT_555RGB                (0x00040000)
+#define PSB_2D_PAT_1555ARGB              (0x00048000)
+#define PSB_2D_PAT_565RGB                (0x00050000)
+#define PSB_2D_PAT_0888ARGB              (0x00058000)
+#define PSB_2D_PAT_8888ARGB              (0x00060000)
+
+#define PSB_2D_PAT_STRIDE_MASK           (0x00007FFF)
+#define PSB_2D_PAT_STRIDE_CLRMASK        (0xFFFF8000)
+#define PSB_2D_PAT_STRIDE_SHIFT          (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_PAT_ADDR_MASK             (0x0FFFFFFC)
+#define PSB_2D_PAT_ADDR_CLRMASK          (0x00000003)
+#define PSB_2D_PAT_ADDR_SHIFT            (2)
+#define PSB_2D_PAT_ADDR_ALIGNSHIFT       (2)
+
+/*
+ * Destination Surface (PSB_2D_DST_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+
+#define PSB_2D_DST_FORMAT_MASK           (0x00078000)
+#define PSB_2D_DST_332RGB                (0x00030000)
+#define PSB_2D_DST_4444ARGB              (0x00038000)
+#define PSB_2D_DST_555RGB                (0x00040000)
+#define PSB_2D_DST_1555ARGB              (0x00048000)
+#define PSB_2D_DST_565RGB                (0x00050000)
+#define PSB_2D_DST_0888ARGB              (0x00058000)
+#define PSB_2D_DST_8888ARGB              (0x00060000)
+#define PSB_2D_DST_8888AYUV              (0x00070000)
+
+#define PSB_2D_DST_STRIDE_MASK           (0x00007FFF)
+#define PSB_2D_DST_STRIDE_CLRMASK        (0xFFFF8000)
+#define PSB_2D_DST_STRIDE_SHIFT          (0)
+/*
+ * WORD 1 - Base Address
+ */
+#define PSB_2D_DST_ADDR_MASK             (0x0FFFFFFC)
+#define PSB_2D_DST_ADDR_CLRMASK          (0x00000003)
+#define PSB_2D_DST_ADDR_SHIFT            (2)
+#define PSB_2D_DST_ADDR_ALIGNSHIFT       (2)
+
+/*
+ * Mask Surface (PSB_2D_MASK_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+#define PSB_2D_MASK_STRIDE_MASK          (0x00007FFF)
+#define PSB_2D_MASK_STRIDE_CLRMASK       (0xFFFF8000)
+#define PSB_2D_MASK_STRIDE_SHIFT         (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_MASK_ADDR_MASK            (0x0FFFFFFC)
+#define PSB_2D_MASK_ADDR_CLRMASK         (0x00000003)
+#define PSB_2D_MASK_ADDR_SHIFT           (2)
+#define PSB_2D_MASK_ADDR_ALIGNSHIFT      (2)
+
+/*
+ * Source Palette (PSB_2D_SRC_PAL_BH)
+ */
+
+#define PSB_2D_SRCPAL_ADDR_SHIFT         (0)
+#define PSB_2D_SRCPAL_ADDR_CLRMASK       (0xF0000007)
+#define PSB_2D_SRCPAL_ADDR_MASK          (0x0FFFFFF8)
+#define PSB_2D_SRCPAL_BYTEALIGN          (1024)
+
+/*
+ * Pattern Palette (PSB_2D_PAT_PAL_BH)
+ */
+
+#define PSB_2D_PATPAL_ADDR_SHIFT         (0)
+#define PSB_2D_PATPAL_ADDR_CLRMASK       (0xF0000007)
+#define PSB_2D_PATPAL_ADDR_MASK          (0x0FFFFFF8)
+#define PSB_2D_PATPAL_BYTEALIGN          (1024)
+
+/*
+ * Rop3 Codes (2 LS bytes)
+ */
+
+#define PSB_2D_ROP3_SRCCOPY              (0xCCCC)
+#define PSB_2D_ROP3_PATCOPY              (0xF0F0)
+#define PSB_2D_ROP3_WHITENESS            (0xFFFF)
+#define PSB_2D_ROP3_BLACKNESS            (0x0000)
+#define PSB_2D_ROP3_SRC                  (0xCC)
+#define PSB_2D_ROP3_PAT                  (0xF0)
+#define PSB_2D_ROP3_DST                  (0xAA)
+
+
+/*
+ * Sizes.
+ */
+
+#define PSB_SCENE_HW_COOKIE_SIZE 16
+#define PSB_TA_MEM_HW_COOKIE_SIZE 16
+
+/*
+ * Scene stuff.
+ */
+
+#define PSB_NUM_HW_SCENES          2
+
+/*
+ * Scheduler completion actions.
+ */
+
+#define PSB_RASTER_BLOCK 0
+#define PSB_RASTER       1
+#define PSB_RETURN       2
+#define PSB_TA       3
+
+
+/*Power management*/
+#define PSB_PUNIT_PORT             0x04
+#define PSB_OSPMBA                 0x78
+#define PSB_APMBA                  0x7a
+#define PSB_APM_CMD                0x0
+#define PSB_APM_STS                0x04
+#define PSB_PWRGT_VID_ENC_MASK     0x30
+#define PSB_PWRGT_VID_DEC_MASK     0xc
+#define PSB_PWRGT_GL3_MASK         0xc0
+
+#define PSB_PM_SSC                 0x20
+#define PSB_PM_SSS                 0x30
+#define PSB_PWRGT_DISPLAY_MASK     0xc /*on a different BA than video/gfx*/
+#define MDFLD_PWRGT_DISPLAY_A_CNTR  0x0000000c 
+#define MDFLD_PWRGT_DISPLAY_B_CNTR  0x0000c000 
+#define MDFLD_PWRGT_DISPLAY_C_CNTR  0x00030000 
+#define MDFLD_PWRGT_DISP_MIPI_CNTR  0x000c0000 
+#define MDFLD_PWRGT_DISPLAY_CNTR    (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR)// 0x000fc00c
+// Display SSS register bits are different in A0 vs. B0
+#define PSB_PWRGT_ISP_MASK        0xc00
+#define PSB_PWRGT_GFX_MASK         0x3
+#define MDFLD_PWRGT_DISPLAY_A_STS              0x000000c0
+#define MDFLD_PWRGT_DISPLAY_B_STS              0x00000300
+#define MDFLD_PWRGT_DISPLAY_C_STS              0x00000c00
+#define MDFLD_PWRGT_DISPLAY_A_STS_B0   0x0000000c
+#define MDFLD_PWRGT_DISPLAY_B_STS_B0   0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_STS_B0   0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_STS  0x000c0000 
+#define MDFLD_PWRGT_DISPLAY_STS_A0    (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS)// 0x000fc00c
+#define MDFLD_PWRGT_DISPLAY_STS_B0    (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS)// 0x000fc00c
+#endif
diff --git a/drivers/staging/mrst/drv/psb_reset.c b/drivers/staging/mrst/drv/psb_reset.c
new file mode 100644 (file)
index 0000000..d15266e
--- /dev/null
@@ -0,0 +1,50 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include <linux/spinlock.h>
+
+void psb_msvdx_flush_cmd_queue(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_msvdx_cmd_queue *msvdx_cmd;
+       struct list_head *list, *next;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       /*Flush the msvdx cmd queue and signal all fences in the queue */
+       list_for_each_safe(list, next, &msvdx_priv->msvdx_queue) {
+               msvdx_cmd =
+                       list_entry(list, struct psb_msvdx_cmd_queue, head);
+               PSB_DEBUG_GENERAL("MSVDXQUE: flushing sequence:%d\n",
+                                 msvdx_cmd->sequence);
+               msvdx_priv->msvdx_current_sequence = msvdx_cmd->sequence;
+               psb_fence_error(dev, PSB_ENGINE_VIDEO,
+                               msvdx_priv->msvdx_current_sequence,
+                               _PSB_FENCE_TYPE_EXE, DRM_CMD_HANG);
+               list_del(list);
+               kfree(msvdx_cmd->cmd);
+               kfree(msvdx_cmd
+                    );
+       }
+}
diff --git a/drivers/staging/mrst/drv/psb_schedule.c b/drivers/staging/mrst/drv/psb_schedule.c
new file mode 100644 (file)
index 0000000..46fc5e8
--- /dev/null
@@ -0,0 +1,70 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "ttm/ttm_execbuf_util.h"
+
+
+static void psb_powerdown_topaz(struct work_struct *work)
+{
+       struct psb_scheduler *scheduler =
+               container_of(work, struct psb_scheduler, topaz_suspend_wq.work);
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) scheduler->dev->dev_private;
+
+       if (!dev_priv->topaz_disabled) {
+               if (!mutex_trylock(&scheduler->topaz_power_mutex))
+                       return;
+
+               ospm_apm_power_down_topaz(scheduler->dev);
+               mutex_unlock(&scheduler->topaz_power_mutex);
+       }
+}
+
+static void psb_powerdown_msvdx(struct work_struct *work)
+{
+       struct psb_scheduler *scheduler =
+               container_of(work, struct psb_scheduler, msvdx_suspend_wq.work);
+
+       if (!mutex_trylock(&scheduler->msvdx_power_mutex))
+               return;
+
+       psb_try_power_down_msvdx(scheduler->dev);
+       mutex_unlock(&scheduler->msvdx_power_mutex);
+}
+
+int psb_scheduler_init(struct drm_device *dev,
+                      struct psb_scheduler *scheduler)
+{
+       memset(scheduler, 0, sizeof(*scheduler));
+       scheduler->dev = dev;
+       mutex_init(&scheduler->topaz_power_mutex);
+       mutex_init(&scheduler->msvdx_power_mutex);
+
+       INIT_DELAYED_WORK(&scheduler->topaz_suspend_wq,
+                         &psb_powerdown_topaz);
+       INIT_DELAYED_WORK(&scheduler->msvdx_suspend_wq,
+                         &psb_powerdown_msvdx);
+
+       return 0;
+}
+
diff --git a/drivers/staging/mrst/drv/psb_schedule.h b/drivers/staging/mrst/drv/psb_schedule.h
new file mode 100644 (file)
index 0000000..764eb29
--- /dev/null
@@ -0,0 +1,81 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ **************************************************************************/
+#ifndef _PSB_SCHEDULE_H_
+#define _PSB_SCHEDULE_H_
+
+#include <drm/drmP.h>
+
+struct psb_context;
+
+enum psb_task_type {
+       psb_flip_task
+};
+
+struct drm_psb_private;
+
+/*struct psb_scheduler_seq {
+       uint32_t sequence;
+       int reported;
+};*/
+
+struct psb_scheduler {
+       struct drm_device *dev;
+       /*struct psb_scheduler_seq seq[_PSB_ENGINE_TA_FENCE_TYPES];
+       struct psb_hw_scene hs[PSB_NUM_HW_SCENES];
+       struct mutex task_wq_mutex;*/
+       struct mutex topaz_power_mutex;
+       struct mutex msvdx_power_mutex;
+       /*spinlock_t lock;
+       struct list_head hw_scenes;
+       struct list_head ta_queue;
+       struct list_head raster_queue;
+       struct list_head hp_raster_queue;
+       struct list_head task_done_queue;
+       struct psb_task *current_task[PSB_SCENE_NUM_ENGINES];
+       struct psb_task *feedback_task;
+       int ta_state;
+       struct psb_hw_scene *pending_hw_scene;
+       uint32_t pending_hw_scene_seq;
+       struct delayed_work wq*/;
+       struct delayed_work topaz_suspend_wq;
+       struct delayed_work msvdx_suspend_wq;
+       /*struct psb_scene_pool *pool;
+       uint32_t idle_count;
+       int idle;
+       wait_queue_head_t idle_queue;
+       unsigned long ta_end_jiffies;
+       unsigned long total_ta_jiffies;
+       unsigned long raster_end_jiffies;
+       unsigned long total_raster_jiffies;*/
+};
+
+/*#define PSB_RF_FIRE_TA       (1 << 0)
+#define PSB_RF_OOM           (1 << 1)
+#define PSB_RF_OOM_REPLY     (1 << 2)
+#define PSB_RF_TERMINATE     (1 << 3)
+#define PSB_RF_TA_DONE       (1 << 4)
+#define PSB_RF_FIRE_RASTER   (1 << 5)
+#define PSB_RF_RASTER_DONE   (1 << 6)
+#define PSB_RF_DEALLOC       (1 << 7)
+*/
+
+extern int psb_scheduler_init(struct drm_device *dev,
+                             struct psb_scheduler *scheduler);
+
+#endif
diff --git a/drivers/staging/mrst/drv/psb_sgx.c b/drivers/staging/mrst/drv/psb_sgx.c
new file mode 100644 (file)
index 0000000..8245e81
--- /dev/null
@@ -0,0 +1,941 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX. USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_drm.h"
+#include "psb_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_execbuf_util.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_placement.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+
+static inline int psb_same_page(unsigned long offset,
+                               unsigned long offset2)
+{
+       return (offset & PAGE_MASK) == (offset2 & PAGE_MASK);
+}
+
+static inline unsigned long psb_offset_end(unsigned long offset,
+               unsigned long end)
+{
+       offset = (offset + PAGE_SIZE) & PAGE_MASK;
+       return (end < offset) ? end : offset;
+}
+
+static void psb_idle_engine(struct drm_device *dev, int engine);
+
+struct psb_dstbuf_cache {
+       unsigned int dst;
+       struct ttm_buffer_object *dst_buf;
+       unsigned long dst_offset;
+       uint32_t *dst_page;
+       unsigned int dst_page_offset;
+       struct ttm_bo_kmap_obj dst_kmap;
+       bool dst_is_iomem;
+};
+
+struct psb_validate_buffer {
+       struct ttm_validate_buffer base;
+       struct psb_validate_req req;
+       int ret;
+       struct psb_validate_arg __user *user_val_arg;
+       uint32_t flags;
+       uint32_t offset;
+       int po_correct;
+};
+
+static int psb_check_presumed(struct psb_validate_req *req,
+                             struct ttm_buffer_object *bo,
+                             struct psb_validate_arg __user *data,
+                             int *presumed_ok)
+{
+       struct psb_validate_req __user *user_req = &(data->d.req);
+
+       *presumed_ok = 0;
+
+       if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+               *presumed_ok = 1;
+               return 0;
+       }
+
+       if (unlikely(!(req->presumed_flags & PSB_USE_PRESUMED)))
+               return 0;
+
+       if (bo->offset == req->presumed_gpu_offset) {
+               *presumed_ok = 1;
+               return 0;
+       }
+
+       return __put_user(req->presumed_flags & ~PSB_USE_PRESUMED,
+                         &user_req->presumed_flags);
+}
+
+
+static void psb_unreference_buffers(struct psb_context *context)
+{
+       struct ttm_validate_buffer *entry, *next;
+       struct psb_validate_buffer *vbuf;
+       struct list_head *list = &context->validate_list;
+
+       list_for_each_entry_safe(entry, next, list, head) {
+               vbuf =
+                       container_of(entry, struct psb_validate_buffer, base);
+               list_del(&entry->head);
+               ttm_bo_unref(&entry->bo);
+       }
+
+       list = &context->kern_validate_list;
+
+       list_for_each_entry_safe(entry, next, list, head) {
+               vbuf =
+                       container_of(entry, struct psb_validate_buffer, base);
+               list_del(&entry->head);
+               ttm_bo_unref(&entry->bo);
+       }
+}
+
+
+static int psb_lookup_validate_buffer(struct drm_file *file_priv,
+                                     uint64_t data,
+                                     struct psb_validate_buffer *item)
+{
+       struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+
+       item->user_val_arg =
+               (struct psb_validate_arg __user *)(unsigned long) data;
+
+       if (unlikely(copy_from_user(&item->req, &item->user_val_arg->d.req,
+                                   sizeof(item->req)) != 0)) {
+               DRM_ERROR("Lookup copy fault.\n");
+               return -EFAULT;
+       }
+
+       item->base.bo =
+               ttm_buffer_object_lookup(tfile, item->req.buffer_handle);
+
+       if (unlikely(item->base.bo == NULL)) {
+               DRM_ERROR("Bo lookup fault.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int psb_reference_buffers(struct drm_file *file_priv,
+                                uint64_t data,
+                                struct psb_context *context)
+{
+       struct psb_validate_buffer *item;
+       int ret;
+
+       while (likely(data != 0)) {
+               if (unlikely(context->used_buffers >=
+                            PSB_NUM_VALIDATE_BUFFERS)) {
+                       DRM_ERROR("Too many buffers "
+                                 "on validate list.\n");
+                       ret = -EINVAL;
+                       goto out_err0;
+               }
+
+               item = &context->buffers[context->used_buffers];
+
+               ret = psb_lookup_validate_buffer(file_priv, data, item);
+               if (unlikely(ret != 0))
+                       goto out_err0;
+
+               item->base.reserved = 0;
+               list_add_tail(&item->base.head, &context->validate_list);
+               context->used_buffers++;
+               data = item->req.next;
+       }
+       return 0;
+
+out_err0:
+       psb_unreference_buffers(context);
+       return ret;
+}
+
+static int
+psb_placement_fence_type(struct ttm_buffer_object *bo,
+                        uint64_t set_val_flags,
+                        uint64_t clr_val_flags,
+                        uint32_t new_fence_class,
+                        uint32_t *new_fence_type)
+{
+       int ret;
+       uint32_t n_fence_type;
+       /*
+       uint32_t set_flags = set_val_flags & 0xFFFFFFFF;
+       uint32_t clr_flags = clr_val_flags & 0xFFFFFFFF;
+       */
+       struct ttm_fence_object *old_fence;
+       uint32_t old_fence_type;
+       struct ttm_placement placement;
+
+       if (unlikely
+           (!(set_val_flags &
+              (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)))) {
+               DRM_ERROR
+               ("GPU access type (read / write) is not indicated.\n");
+               return -EINVAL;
+       }
+
+       /* User space driver doesn't set any TTM placement flags in set_val_flags or clr_val_flags */
+       placement.num_placement = 0;/* FIXME  */
+       placement.num_busy_placement = 0;
+       placement.fpfn = 0;
+       placement.lpfn = 0;
+       ret = psb_ttm_bo_check_placement(bo, &placement);
+       if (unlikely(ret != 0))
+               return ret;
+
+       switch (new_fence_class) {
+       default:
+               n_fence_type = _PSB_FENCE_TYPE_EXE;
+       }
+
+       *new_fence_type = n_fence_type;
+       old_fence = (struct ttm_fence_object *) bo->sync_obj;
+       old_fence_type = (uint32_t)(unsigned long) bo->sync_obj_arg;
+
+       if (old_fence && ((new_fence_class != old_fence->fence_class) ||
+                         ((n_fence_type ^ old_fence_type) &
+                          old_fence_type))) {
+               ret = ttm_bo_wait(bo, 0, 1, 0);
+               if (unlikely(ret != 0))
+                       return ret;
+       }
+       /*
+       bo->proposed_flags = (bo->proposed_flags | set_flags)
+               & ~clr_flags & TTM_PL_MASK_MEMTYPE;
+       */
+       return 0;
+}
+
+static int psb_validate_buffer_list(struct drm_file *file_priv,
+                                   uint32_t fence_class,
+                                   struct psb_context *context,
+                                   int *po_correct)
+{
+       struct psb_validate_buffer *item;
+       struct ttm_buffer_object *bo;
+       int ret;
+       struct psb_validate_req *req;
+       uint32_t fence_types = 0;
+       uint32_t cur_fence_type;
+       struct ttm_validate_buffer *entry;
+       struct list_head *list = &context->validate_list;
+       struct ttm_placement placement;
+       uint32_t flags;
+
+       *po_correct = 1;
+
+       list_for_each_entry(entry, list, head) {
+               item =
+                       container_of(entry, struct psb_validate_buffer, base);
+               bo = entry->bo;
+               item->ret = 0;
+               req = &item->req;
+
+               spin_lock(&bo->bdev->fence_lock);
+               ret = psb_placement_fence_type(bo,
+                                              req->set_flags,
+                                              req->clear_flags,
+                                              fence_class,
+                                              &cur_fence_type);
+               if (unlikely(ret != 0))
+                       goto out_err_unlock;
+
+               flags = item->req.pad64 | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+               placement.num_placement = 1;
+               placement.placement = &flags;
+               placement.num_busy_placement = 0;
+               placement.fpfn = 0;
+               placement.lpfn = 0;
+               /*
+               ret = ttm_bo_validate(bo, &placement, 1, 0, 0);
+               if (unlikely(ret != 0))
+                       goto out_err_unlock;
+               */
+               fence_types |= cur_fence_type;
+               entry->new_sync_obj_arg = (void *)
+                                         (unsigned long) cur_fence_type;
+
+               item->offset = bo->offset;
+               item->flags = bo->mem.placement;
+               spin_unlock(&bo->bdev->fence_lock);
+
+               ret =
+                       psb_check_presumed(&item->req, bo, item->user_val_arg,
+                                          &item->po_correct);
+               if (unlikely(ret != 0))
+                       goto out_err;
+
+               if (unlikely(!item->po_correct))
+                       *po_correct = 0;
+
+               item++;
+       }
+
+       context->fence_types |= fence_types;
+
+       return 0;
+out_err_unlock:
+       spin_unlock(&bo->bdev->fence_lock);
+out_err:
+       item->ret = ret;
+       return ret;
+}
+
+static void psb_clear_dstbuf_cache(struct psb_dstbuf_cache *dst_cache)
+{
+       if (dst_cache->dst_page) {
+               ttm_bo_kunmap(&dst_cache->dst_kmap);
+               dst_cache->dst_page = NULL;
+       }
+       dst_cache->dst_buf = NULL;
+       dst_cache->dst = ~0;
+}
+
+static int psb_update_dstbuf_cache(struct psb_dstbuf_cache *dst_cache,
+                                  struct psb_validate_buffer *buffers,
+                                  unsigned int dst,
+                                  unsigned long dst_offset)
+{
+       int ret;
+
+       PSB_DEBUG_GENERAL("Destination buffer is %d.\n", dst);
+
+       if (unlikely(dst != dst_cache->dst || NULL == dst_cache->dst_buf)) {
+               psb_clear_dstbuf_cache(dst_cache);
+               dst_cache->dst = dst;
+               dst_cache->dst_buf = buffers[dst].base.bo;
+       }
+
+       if (unlikely
+           (dst_offset > dst_cache->dst_buf->num_pages * PAGE_SIZE)) {
+               DRM_ERROR("Relocation destination out of bounds.\n");
+               return -EINVAL;
+       }
+
+       if (!psb_same_page(dst_cache->dst_offset, dst_offset) ||
+           NULL == dst_cache->dst_page) {
+               if (NULL != dst_cache->dst_page) {
+                       ttm_bo_kunmap(&dst_cache->dst_kmap);
+                       dst_cache->dst_page = NULL;
+               }
+
+               ret =
+                       ttm_bo_kmap(dst_cache->dst_buf,
+                                   dst_offset >> PAGE_SHIFT, 1,
+                                   &dst_cache->dst_kmap);
+               if (ret) {
+                       DRM_ERROR("Could not map destination buffer for "
+                                 "relocation.\n");
+                       return ret;
+               }
+
+               dst_cache->dst_page =
+                       ttm_kmap_obj_virtual(&dst_cache->dst_kmap,
+                                            &dst_cache->dst_is_iomem);
+               dst_cache->dst_offset = dst_offset & PAGE_MASK;
+               dst_cache->dst_page_offset = dst_cache->dst_offset >> 2;
+       }
+       return 0;
+}
+
+static int psb_apply_reloc(struct drm_psb_private *dev_priv,
+                          uint32_t fence_class,
+                          const struct drm_psb_reloc *reloc,
+                          struct psb_validate_buffer *buffers,
+                          int num_buffers,
+                          struct psb_dstbuf_cache *dst_cache,
+                          int no_wait, int interruptible)
+{
+       uint32_t val;
+       uint32_t background;
+       unsigned int index;
+       int ret;
+       unsigned int shift;
+       unsigned int align_shift;
+       struct ttm_buffer_object *reloc_bo;
+
+
+       PSB_DEBUG_GENERAL("Reloc type %d\n"
+                         "\t where 0x%04x\n"
+                         "\t buffer 0x%04x\n"
+                         "\t mask 0x%08x\n"
+                         "\t shift 0x%08x\n"
+                         "\t pre_add 0x%08x\n"
+                         "\t background 0x%08x\n"
+                         "\t dst_buffer 0x%08x\n"
+                         "\t arg0 0x%08x\n"
+                         "\t arg1 0x%08x\n",
+                         reloc->reloc_op,
+                         reloc->where,
+                         reloc->buffer,
+                         reloc->mask,
+                         reloc->shift,
+                         reloc->pre_add,
+                         reloc->background,
+                         reloc->dst_buffer, reloc->arg0, reloc->arg1);
+
+       if (unlikely(reloc->buffer >= num_buffers)) {
+               DRM_ERROR("Illegal relocation buffer %d.\n",
+                         reloc->buffer);
+               return -EINVAL;
+       }
+
+       if (buffers[reloc->buffer].po_correct)
+               return 0;
+
+       if (unlikely(reloc->dst_buffer >= num_buffers)) {
+               DRM_ERROR
+               ("Illegal destination buffer for relocation %d.\n",
+                reloc->dst_buffer);
+               return -EINVAL;
+       }
+
+       ret =
+               psb_update_dstbuf_cache(dst_cache, buffers, reloc->dst_buffer,
+                                       reloc->where << 2);
+       if (ret)
+               return ret;
+
+       reloc_bo = buffers[reloc->buffer].base.bo;
+
+       if (unlikely(reloc->pre_add > (reloc_bo->num_pages << PAGE_SHIFT))) {
+               DRM_ERROR("Illegal relocation offset add.\n");
+               return -EINVAL;
+       }
+
+       switch (reloc->reloc_op) {
+       case PSB_RELOC_OP_OFFSET:
+               val = reloc_bo->offset + reloc->pre_add;
+               break;
+       default:
+               DRM_ERROR("Unimplemented relocation.\n");
+               return -EINVAL;
+       }
+
+       shift =
+               (reloc->shift & PSB_RELOC_SHIFT_MASK) >> PSB_RELOC_SHIFT_SHIFT;
+       align_shift =
+               (reloc->
+                shift & PSB_RELOC_ALSHIFT_MASK) >> PSB_RELOC_ALSHIFT_SHIFT;
+
+       val = ((val >> align_shift) << shift);
+       index = reloc->where - dst_cache->dst_page_offset;
+
+       background = reloc->background;
+       val = (background & ~reloc->mask) | (val & reloc->mask);
+       dst_cache->dst_page[index] = val;
+
+       PSB_DEBUG_GENERAL("Reloc buffer %d index 0x%08x, value 0x%08x\n",
+                         reloc->dst_buffer, index,
+                         dst_cache->dst_page[index]);
+
+       return 0;
+}
+
+static int psb_ok_to_map_reloc(struct drm_psb_private *dev_priv,
+                              unsigned int num_pages)
+{
+       int ret = 0;
+
+       spin_lock(&dev_priv->reloc_lock);
+       if (dev_priv->rel_mapped_pages + num_pages <= PSB_MAX_RELOC_PAGES) {
+               dev_priv->rel_mapped_pages += num_pages;
+               ret = 1;
+       }
+       spin_unlock(&dev_priv->reloc_lock);
+       return ret;
+}
+
+static int psb_fixup_relocs(struct drm_file *file_priv,
+                           uint32_t fence_class,
+                           unsigned int num_relocs,
+                           unsigned int reloc_offset,
+                           uint32_t reloc_handle,
+                           struct psb_context *context,
+                           int no_wait, int interruptible)
+{
+       struct drm_device *dev = file_priv->minor->dev;
+       struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct ttm_buffer_object *reloc_buffer = NULL;
+       unsigned int reloc_num_pages;
+       unsigned int reloc_first_page;
+       unsigned int reloc_last_page;
+       struct psb_dstbuf_cache dst_cache;
+       struct drm_psb_reloc *reloc;
+       struct ttm_bo_kmap_obj reloc_kmap;
+       bool reloc_is_iomem;
+       int count;
+       int ret = 0;
+       int registered = 0;
+       uint32_t num_buffers = context->used_buffers;
+
+       if (num_relocs == 0)
+               return 0;
+
+       memset(&dst_cache, 0, sizeof(dst_cache));
+       memset(&reloc_kmap, 0, sizeof(reloc_kmap));
+
+       reloc_buffer = ttm_buffer_object_lookup(tfile, reloc_handle);
+       if (!reloc_buffer)
+               goto out;
+
+       if (unlikely(atomic_read(&reloc_buffer->reserved) != 1)) {
+               DRM_ERROR("Relocation buffer was not on validate list.\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       reloc_first_page = reloc_offset >> PAGE_SHIFT;
+       reloc_last_page =
+               (reloc_offset +
+                num_relocs * sizeof(struct drm_psb_reloc)) >> PAGE_SHIFT;
+       reloc_num_pages = reloc_last_page - reloc_first_page + 1;
+       reloc_offset &= ~PAGE_MASK;
+
+       if (reloc_num_pages > PSB_MAX_RELOC_PAGES) {
+               DRM_ERROR("Relocation buffer is too large\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       DRM_WAIT_ON(ret, dev_priv->rel_mapped_queue, 3 * DRM_HZ,
+                   (registered =
+                            psb_ok_to_map_reloc(dev_priv, reloc_num_pages)));
+
+       if (ret == -EINTR) {
+               ret = -ERESTART;
+               goto out;
+       }
+       if (ret) {
+               DRM_ERROR("Error waiting for space to map "
+                         "relocation buffer.\n");
+               goto out;
+       }
+
+       ret = ttm_bo_kmap(reloc_buffer, reloc_first_page,
+                         reloc_num_pages, &reloc_kmap);
+
+       if (ret) {
+               DRM_ERROR("Could not map relocation buffer.\n"
+                         "\tReloc buffer id 0x%08x.\n"
+                         "\tReloc first page %d.\n"
+                         "\tReloc num pages %d.\n",
+                         reloc_handle, reloc_first_page, reloc_num_pages);
+               goto out;
+       }
+
+       reloc = (struct drm_psb_reloc *)
+               ((unsigned long)
+                ttm_kmap_obj_virtual(&reloc_kmap,
+                                     &reloc_is_iomem) + reloc_offset);
+
+       for (count = 0; count < num_relocs; ++count) {
+               ret = psb_apply_reloc(dev_priv, fence_class,
+                                     reloc, context->buffers,
+                                     num_buffers, &dst_cache,
+                                     no_wait, interruptible);
+               if (ret)
+                       goto out1;
+               reloc++;
+       }
+
+out1:
+       ttm_bo_kunmap(&reloc_kmap);
+out:
+       if (registered) {
+               spin_lock(&dev_priv->reloc_lock);
+               dev_priv->rel_mapped_pages -= reloc_num_pages;
+               spin_unlock(&dev_priv->reloc_lock);
+               DRM_WAKEUP(&dev_priv->rel_mapped_queue);
+       }
+
+       psb_clear_dstbuf_cache(&dst_cache);
+       if (reloc_buffer)
+               ttm_bo_unref(&reloc_buffer);
+       return ret;
+}
+
+void psb_fence_or_sync(struct drm_file *file_priv,
+                      uint32_t engine,
+                      uint32_t fence_types,
+                      uint32_t fence_flags,
+                      struct list_head *list,
+                      struct psb_ttm_fence_rep *fence_arg,
+                      struct ttm_fence_object **fence_p)
+{
+       struct drm_device *dev = file_priv->minor->dev;
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct ttm_fence_device *fdev = &dev_priv->fdev;
+       int ret;
+       struct ttm_fence_object *fence;
+       struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+       uint32_t handle;
+
+       ret = ttm_fence_user_create(fdev, tfile,
+                                   engine, fence_types,
+                                   TTM_FENCE_FLAG_EMIT, &fence, &handle);
+       if (ret) {
+
+               /*
+                * Fence creation failed.
+                * Fall back to synchronous operation and idle the engine.
+                */
+
+               psb_idle_engine(dev, engine);
+               if (!(fence_flags & DRM_PSB_FENCE_NO_USER)) {
+
+                       /*
+                        * Communicate to user-space that
+                        * fence creation has failed and that
+                        * the engine is idle.
+                        */
+
+                       fence_arg->handle = ~0;
+                       fence_arg->error = ret;
+               }
+
+               ttm_eu_backoff_reservation(list);
+               if (fence_p)
+                       *fence_p = NULL;
+               return;
+       }
+
+       ttm_eu_fence_buffer_objects(list, fence);
+       if (!(fence_flags & DRM_PSB_FENCE_NO_USER)) {
+               struct ttm_fence_info info = ttm_fence_get_info(fence);
+               fence_arg->handle = handle;
+               fence_arg->fence_class = ttm_fence_class(fence);
+               fence_arg->fence_type = ttm_fence_types(fence);
+               fence_arg->signaled_types = info.signaled_types;
+               fence_arg->error = 0;
+       } else {
+               ret =
+                       ttm_ref_object_base_unref(tfile, handle,
+                                                 ttm_fence_type);
+               BUG_ON(ret);
+       }
+
+       if (fence_p)
+               *fence_p = fence;
+       else if (fence)
+               ttm_fence_object_unref(&fence);
+}
+
+
+#if 0
+static int psb_dump_page(struct ttm_buffer_object *bo,
+                        unsigned int page_offset, unsigned int num)
+{
+       struct ttm_bo_kmap_obj kmobj;
+       int is_iomem;
+       uint32_t *p;
+       int ret;
+       unsigned int i;
+
+       ret = ttm_bo_kmap(bo, page_offset, 1, &kmobj);
+       if (ret)
+               return ret;
+
+       p = ttm_kmap_obj_virtual(&kmobj, &is_iomem);
+       for (i = 0; i < num; ++i)
+               PSB_DEBUG_GENERAL("0x%04x: 0x%08x\n", i, *p++);
+
+       ttm_bo_kunmap(&kmobj);
+       return 0;
+}
+#endif
+
+static void psb_idle_engine(struct drm_device *dev, int engine)
+{
+       /*Fix me add video engile support*/
+       return;
+}
+
+static int psb_handle_copyback(struct drm_device *dev,
+                              struct psb_context *context,
+                              int ret)
+{
+       int err = ret;
+       struct ttm_validate_buffer *entry;
+       struct psb_validate_arg arg;
+       struct list_head *list = &context->validate_list;
+
+       if (ret) {
+               ttm_eu_backoff_reservation(list);
+               ttm_eu_backoff_reservation(&context->kern_validate_list);
+       }
+
+
+       if (ret != -EAGAIN && ret != -EINTR && ret != -ERESTART) {
+               list_for_each_entry(entry, list, head) {
+                       struct psb_validate_buffer *vbuf =
+                               container_of(entry, struct psb_validate_buffer,
+                                            base);
+                       arg.handled = 1;
+                       arg.ret = vbuf->ret;
+                       if (!arg.ret) {
+                               struct ttm_buffer_object *bo = entry->bo;
+                               spin_lock(&bo->bdev->fence_lock);
+                               arg.d.rep.gpu_offset = bo->offset;
+                               arg.d.rep.placement = bo->mem.placement;
+                               arg.d.rep.fence_type_mask =
+                                       (uint32_t)(unsigned long)
+                                       entry->new_sync_obj_arg;
+                               spin_unlock(&bo->bdev->fence_lock);
+                       }
+
+                       if (__copy_to_user(vbuf->user_val_arg,
+                                          &arg, sizeof(arg)))
+                               err = -EFAULT;
+
+                       if (arg.ret)
+                               break;
+               }
+       }
+
+       return err;
+}
+
+int psb_cmdbuf_ioctl(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
+{
+       struct drm_psb_cmdbuf_arg *arg = data;
+       int ret = 0;
+       struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+       struct ttm_buffer_object *cmd_buffer = NULL;
+       struct psb_ttm_fence_rep fence_arg;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)file_priv->minor->dev->dev_private;
+       struct psb_video_ctx *pos, *n;
+       int engine;
+       int po_correct;
+       struct psb_context *context;
+       unsigned num_buffers;
+
+       ((struct msvdx_private*)dev_priv->msvdx_private)->tfile = tfile;
+       num_buffers = PSB_NUM_VALIDATE_BUFFERS;
+
+       ret = ttm_read_lock(&dev_priv->ttm_lock, true);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (arg->engine == PSB_ENGINE_VIDEO) {
+               if (!ospm_power_using_hw_begin(OSPM_VIDEO_DEC_ISLAND,
+                                              OSPM_UHB_FORCE_POWER_ON))
+                       return -EBUSY;
+       } else if (arg->engine == LNC_ENGINE_ENCODE) {
+               if (dev_priv->topaz_disabled)
+                       return -ENODEV;
+
+               if (!ospm_power_using_hw_begin(OSPM_VIDEO_ENC_ISLAND,
+                                              OSPM_UHB_FORCE_POWER_ON))
+                       return -EBUSY;
+       }
+
+
+       ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+       if (unlikely(ret != 0))
+               goto out_err0;
+
+
+       context = &dev_priv->context;
+       context->used_buffers = 0;
+       context->fence_types = 0;
+       BUG_ON(!list_empty(&context->validate_list));
+       BUG_ON(!list_empty(&context->kern_validate_list));
+
+       if (unlikely(context->buffers == NULL)) {
+               context->buffers = vmalloc(PSB_NUM_VALIDATE_BUFFERS *
+                                          sizeof(*context->buffers));
+               if (unlikely(context->buffers == NULL)) {
+                       ret = -ENOMEM;
+                       goto out_err1;
+               }
+       }
+
+       ret = psb_reference_buffers(file_priv,
+                                   arg->buffer_list,
+                                   context);
+
+       if (unlikely(ret != 0))
+               goto out_err1;
+
+       ret = ttm_eu_reserve_buffers(&context->validate_list);
+       if (unlikely(ret != 0))
+               goto out_err2;
+
+       engine = arg->engine;
+       ret = psb_validate_buffer_list(file_priv, engine,
+                                      context, &po_correct);
+       if (unlikely(ret != 0))
+               goto out_err3;
+
+       if (!po_correct) {
+               ret = psb_fixup_relocs(file_priv, engine, arg->num_relocs,
+                                      arg->reloc_offset,
+                                      arg->reloc_handle, context, 0, 1);
+               if (unlikely(ret != 0))
+                       goto out_err3;
+
+       }
+
+       cmd_buffer = ttm_buffer_object_lookup(tfile, arg->cmdbuf_handle);
+       if (unlikely(cmd_buffer == NULL)) {
+               ret = -EINVAL;
+               goto out_err4;
+       }
+
+       list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+               if (pos->filp == file_priv->filp) {
+                       int entrypoint = pos->ctx_type & 0xff;
+
+                       PSB_DEBUG_GENERAL("Video:commands for profile %d, entrypoint %d",
+                                         (pos->ctx_type >> 8), (pos->ctx_type & 0xff));
+
+                       if (entrypoint == VAEntrypointEncSlice ||
+                           entrypoint == VAEntrypointEncPicture)
+                               dev_priv->topaz_ctx = pos;
+                       else
+                               dev_priv->msvdx_ctx = pos;
+
+                       break;
+               }
+       }
+
+       switch (arg->engine) {
+       case PSB_ENGINE_VIDEO:
+               if (arg->cmdbuf_size == (16 + 32)) {
+                       /* Identify deblock msg cmdbuf */
+                       /* according to cmdbuf_size */
+                       struct ttm_bo_kmap_obj cmd_kmap;
+                       struct ttm_buffer_object *deblock;
+                       uint32_t *cmd;
+                       bool is_iomem;
+
+                       /* write regIO BO's address after deblcok msg */
+                       ret = ttm_bo_kmap(cmd_buffer, 0, 1, &cmd_kmap);
+                       if (unlikely(ret != 0))
+                               goto out_err4;
+                       cmd = (uint32_t *)(ttm_kmap_obj_virtual(&cmd_kmap,
+                                                               &is_iomem) + 16);
+                       deblock = ttm_buffer_object_lookup(tfile,
+                                                          (uint32_t)(*cmd));
+                       *cmd = (uint32_t)deblock;
+                       ttm_bo_unref(&deblock); /* FIXME Should move this to interrupt handler? */
+                       ttm_bo_kunmap(&cmd_kmap);
+               }
+
+               ret = psb_cmdbuf_video(file_priv, &context->validate_list,
+                                      context->fence_types, arg,
+                                      cmd_buffer, &fence_arg);
+
+               if (unlikely(ret != 0))
+                       goto out_err4;
+               break;
+       case LNC_ENGINE_ENCODE:
+               ret = pnw_cmdbuf_video(file_priv, &context->validate_list,
+                               context->fence_types, arg,
+                               cmd_buffer, &fence_arg);
+
+               if (unlikely(ret != 0))
+                       goto out_err4;
+               break;
+
+
+       default:
+               DRM_ERROR
+               ("Unimplemented command submission mechanism (%x).\n",
+                arg->engine);
+               ret = -EINVAL;
+               goto out_err4;
+       }
+
+       if (!(arg->fence_flags & DRM_PSB_FENCE_NO_USER)) {
+               ret = copy_to_user((void __user *)
+                                  ((unsigned long) arg->fence_arg),
+                                  &fence_arg, sizeof(fence_arg));
+       }
+
+out_err4:
+       if (cmd_buffer)
+               ttm_bo_unref(&cmd_buffer);
+out_err3:
+       ret = psb_handle_copyback(dev, context, ret);
+out_err2:
+       psb_unreference_buffers(context);
+out_err1:
+       mutex_unlock(&dev_priv->cmdbuf_mutex);
+out_err0:
+       ttm_read_unlock(&dev_priv->ttm_lock);
+
+       if (arg->engine == PSB_ENGINE_VIDEO)
+               ospm_power_using_hw_end(OSPM_VIDEO_DEC_ISLAND);
+
+       if (arg->engine == LNC_ENGINE_ENCODE)
+               ospm_power_using_hw_end(OSPM_VIDEO_ENC_ISLAND);
+
+       return ret;
+}
+
+void psb_gl3_global_invalidation(struct drm_device *dev)
+{
+#ifdef CONFIG_MDFD_GL3
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t gl3_ctl;
+       /* uint32_t poll_count = 0x1000, gl3_stat; */
+
+       /* IS there a way to avoid multiple invalidation simultaneously? Maybe a ATOM value */
+
+       gl3_ctl = PSB_RVDC32(PSB_GL3_CACHE_CTL);
+       /* gl3_ctl = PSB_RVDC32(0xb0000); */
+       /* printk("gl3_invalidation: GCL_CR_CTL2 is 0x%08x\n", gl3_ctl); */
+
+       PSB_WVDC32(gl3_ctl | 0x2, PSB_GL3_CACHE_CTL);
+
+#if 0
+       while (poll_count) {
+               gl3_stat = PSB_RVDC32(PSB_GL3_CACHE_STAT);
+               if (gl3_stat & 0x1) {
+                       PSB_WVDC32(gl3_stat | 0x1, PSB_GL3_CACHE_STAT); /* Frome D.Will : write 1 to Inval_done bit to clear it */
+                       return;
+               }
+               cpu_relax();
+               poll_count--;
+       }
+
+       DRM_ERROR("Invalidation GL3 timeout\n");
+#endif
+#endif
+}
diff --git a/drivers/staging/mrst/drv/psb_socket.c b/drivers/staging/mrst/drv/psb_socket.c
new file mode 100644 (file)
index 0000000..b1415b2
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004 Novell, Inc.  All rights reserved.
+ * Copyright (C) 2004 IBM, Inc. All rights reserved.
+ * Copyright (C) 2009 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the GNU GPL v2.
+ *
+ * Authors:
+ *     Robert Love             <rml@novell.com>
+ *     Kay Sievers             <kay.sievers@vrfy.org>
+ *     Arjan van de Ven        <arjanv@redhat.com>
+ *     Greg Kroah-Hartman      <greg@kroah.com>
+ *
+ * Notes:
+ *      Adapted from existing kobj event socket code to enable
+ *      mutlicast usermode communication for gfx driver to mutiple
+ *      usermode threads via different socket broadcast groups.
+ *      Original kobject uevent code does not allow for different
+ *      broadcast groups.  Due to the frequency of usermode events
+ *      generated by some gfx subsystems it is necessary to open
+ *      a new dedicated socket with multicast group support.  In
+ *      the future it is hoped that this code can be removed
+ *      and either a new netlink protocol type added for graphics
+ *      or conversely to simply enable group routing to be leveraged
+ *      on the existing kobject uevent infrastructure.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <net/sock.h>
+#include "psb_umevents.h"
+
+#define NETLINK_PSB_KOBJECT_UEVENT     31
+
+static u64 psb_uevent_seqnum;
+static char psb_uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
+static DEFINE_SPINLOCK(sequence_lock);
+#if defined(CONFIG_NET)
+static struct sock *uevent_sock;
+#endif
+
+/* the strings here must match the enum in include/linux/kobject.h */
+static const char *psb_kobject_actions[] = {
+       [KOBJ_ADD] =            "add",
+       [KOBJ_REMOVE] =         "remove",
+       [KOBJ_CHANGE] =         "change",
+       [KOBJ_MOVE] =           "move",
+       [KOBJ_ONLINE] =         "online",
+       [KOBJ_OFFLINE] =        "offline",
+};
+
+/**
+ * kobject_action_type - translate action string to numeric type
+ *
+ * @buf: buffer containing the action string, newline is ignored
+ * @len: length of buffer
+ * @type: pointer to the location to store the action type
+ *
+ * Returns 0 if the action string was recognized.
+ */
+int psb_kobject_action_type(const char *buf, size_t count,
+                       enum kobject_action *type)
+{
+       enum kobject_action action;
+       int ret = -EINVAL;
+
+       if (count && (buf[count-1] == '\n' || buf[count-1] == '\0'))
+               count--;
+
+       if (!count)
+               goto out;
+
+       for (action = 0; action < ARRAY_SIZE(psb_kobject_actions); action++) {
+               if (strncmp(psb_kobject_actions[action], buf, count) != 0)
+                       continue;
+               if (psb_kobject_actions[action][count] != '\0')
+                       continue;
+               *type = action;
+               ret = 0;
+               break;
+       }
+out:
+       return ret;
+}
+
+/**
+ * psb_kobject_uevent_env - send an uevent with environmental data
+ *
+ * @action: action that is happening
+ * @kobj: struct kobject that the action is happening to
+ * @envp_ext: pointer to environmental data
+ *
+ * Returns 0 if kobject_uevent() is completed with success or the
+ * corresponding error when it fails.
+ */
+int psb_kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+                          char *envp_ext[], int dst_group_id)
+{
+       struct kobj_uevent_env *env;
+       const char *action_string = psb_kobject_actions[action];
+       const char *devpath = NULL;
+       const char *subsystem;
+       struct kobject *top_kobj;
+       struct kset *kset;
+       struct kset_uevent_ops *uevent_ops;
+       u64 seq;
+       int i = 0;
+       int retval = 0;
+
+       pr_debug("kobject: '%s' (%p): %s\n",
+                kobject_name(kobj), kobj, __func__);
+
+       /* search the kset we belong to */
+       top_kobj = kobj;
+       while (!top_kobj->kset && top_kobj->parent)
+               top_kobj = top_kobj->parent;
+
+       if (!top_kobj->kset) {
+               pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
+                        "without kset!\n", kobject_name(kobj), kobj,
+                        __func__);
+               return -EINVAL;
+       }
+
+       kset = top_kobj->kset;
+       uevent_ops = (struct kset_uevent_ops *)kset->uevent_ops;
+
+       /* skip the event, if uevent_suppress is set*/
+       if (kobj->uevent_suppress) {
+               pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
+                                "caused the event to drop!\n",
+                                kobject_name(kobj), kobj, __func__);
+               return 0;
+       }
+       /* skip the event, if the filter returns zero. */
+       if (uevent_ops && uevent_ops->filter)
+               if (!uevent_ops->filter(kset, kobj)) {
+                       pr_debug("kobject: '%s' (%p): %s: filter function "
+                                "caused the event to drop!\n",
+                                kobject_name(kobj), kobj, __func__);
+                       return 0;
+               }
+
+       /* originating subsystem */
+       if (uevent_ops && uevent_ops->name)
+               subsystem = uevent_ops->name(kset, kobj);
+       else
+               subsystem = kobject_name(&kset->kobj);
+       if (!subsystem) {
+               pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
+                        "event to drop!\n", kobject_name(kobj), kobj,
+                        __func__);
+               return 0;
+       }
+
+       /* environment buffer */
+       env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
+       if (!env)
+               return -ENOMEM;
+
+       /* complete object path */
+       devpath = kobject_get_path(kobj, GFP_KERNEL);
+       if (!devpath) {
+               retval = -ENOENT;
+               goto exit;
+       }
+
+       /* default keys */
+       retval = add_uevent_var(env, "ACTION=%s", action_string);
+       if (retval)
+               goto exit;
+       retval = add_uevent_var(env, "DEVPATH=%s", devpath);
+       if (retval)
+               goto exit;
+       retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
+       if (retval)
+               goto exit;
+
+       /* keys passed in from the caller */
+       if (envp_ext) {
+               for (i = 0; envp_ext[i]; i++) {
+                       retval = add_uevent_var(env, "%s", envp_ext[i]);
+                       if (retval)
+                               goto exit;
+               }
+       }
+
+       /* let the kset specific function add its stuff */
+       if (uevent_ops && uevent_ops->uevent) {
+               retval = uevent_ops->uevent(kset, kobj, env);
+               if (retval) {
+                       pr_debug("kobject: '%s' (%p): %s: uevent() returned "
+                                "%d\n", kobject_name(kobj), kobj,
+                                __func__, retval);
+                       goto exit;
+               }
+       }
+
+       /*
+        * Mark "add" and "remove" events in the object to ensure proper
+        * events to userspace during automatic cleanup. If the object did
+        * send an "add" event, "remove" will automatically generated by
+        * the core, if not already done by the caller.
+        */
+       if (action == KOBJ_ADD)
+               kobj->state_add_uevent_sent = 1;
+       else if (action == KOBJ_REMOVE)
+               kobj->state_remove_uevent_sent = 1;
+
+       /* we will send an event, so request a new sequence number */
+       spin_lock(&sequence_lock);
+       seq = ++psb_uevent_seqnum;
+       spin_unlock(&sequence_lock);
+       retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
+       if (retval)
+               goto exit;
+
+#if defined(CONFIG_NET)
+       /* send netlink message */
+       if (uevent_sock) {
+               struct sk_buff *skb;
+               size_t len;
+
+               /* allocate message with the maximum possible size */
+               len = strlen(action_string) + strlen(devpath) + 2;
+               skb = alloc_skb(len + env->buflen, GFP_KERNEL);
+               if (skb) {
+                       char *scratch;
+
+                       /* add header */
+                       scratch = skb_put(skb, len);
+                       sprintf(scratch, "%s@%s", action_string, devpath);
+
+                       /* copy keys to our continuous event payload buffer */
+                       for (i = 0; i < env->envp_idx; i++) {
+                               len = strlen(env->envp[i]) + 1;
+                               scratch = skb_put(skb, len);
+                               strcpy(scratch, env->envp[i]);
+                       }
+
+                       NETLINK_CB(skb).dst_group = dst_group_id;
+                       retval = netlink_broadcast(uevent_sock, skb, 0,
+                                                  dst_group_id,
+                                                  GFP_KERNEL);
+
+                       /* ENOBUFS should be handled in userspace */
+                       if (retval == -ENOBUFS)
+                               retval = 0;
+               } else
+                       retval = -ENOMEM;
+       }
+#endif
+
+       /* call psb_uevent_helper, usually only enabled during early boot */
+       if (psb_uevent_helper[0]) {
+               char *argv[3];
+
+               argv[0] = psb_uevent_helper;
+               argv[1] = (char *)subsystem;
+               argv[2] = NULL;
+               retval = add_uevent_var(env, "HOME=/");
+               if (retval)
+                       goto exit;
+               retval = add_uevent_var(env,
+                                       "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
+               if (retval)
+                       goto exit;
+
+               retval = call_usermodehelper(argv[0], argv,
+                                            env->envp, UMH_WAIT_EXEC);
+       }
+
+exit:
+       kfree(devpath);
+       kfree(env);
+       return retval;
+}
+/*EXPORT_SYMBOL_GPL(psb_kobject_uevent_env); */
+
+/**
+ * psb_kobject_uevent - notify userspace by ending an uevent
+ *
+ * @action: action that is happening
+ * @kobj: struct kobject that the action is happening to
+ *
+ * Returns 0 if psb_kobject_uevent() is completed with success or the
+ * corresponding error when it fails.
+ */
+int psb_kobject_uevent(struct kobject *kobj, enum kobject_action action,
+                      int dst_group_id)
+{
+       return psb_kobject_uevent_env(kobj, action, NULL, dst_group_id);
+}
+/*EXPORT_SYMBOL_GPL(psb_kobject_uevent); */
+
+/**
+ * psb_add_uevent_var - add key value string to the environment buffer
+ * @env: environment buffer structure
+ * @format: printf format for the key=value pair
+ *
+ * Returns 0 if environment variable was added successfully or -ENOMEM
+ * if no space was available.
+ */
+int psb_add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
+{
+       va_list args;
+       int len;
+
+       if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
+               WARN(1, KERN_ERR "psb_add_uevent_var: too many keys\n");
+               return -ENOMEM;
+       }
+
+       va_start(args, format);
+       len = vsnprintf(&env->buf[env->buflen],
+                       sizeof(env->buf) - env->buflen,
+                       format, args);
+       va_end(args);
+
+       if (len >= (sizeof(env->buf) - env->buflen)) {
+               WARN(1,
+                    KERN_ERR "psb_add_uevent_var: buffer size too small\n");
+               return -ENOMEM;
+       }
+
+       env->envp[env->envp_idx++] = &env->buf[env->buflen];
+       env->buflen += len + 1;
+       return 0;
+}
+/*EXPORT_SYMBOL_GPL(psb_add_uevent_var);*/ 
+
+#if defined(CONFIG_NET)
+int __init psb_kobject_uevent_init(void)
+{
+       /* This should be the 15, but 3 seems to work better.  Why? WHY!? */
+       /* uevent_sock = netlink_kernel_create(&init_net,
+                                           NETLINK_PSB_KOBJECT_UEVENT,
+                                           DRM_GFX_SOCKET_GROUPS,
+                                           NULL, NULL, THIS_MODULE); */
+       uevent_sock = netlink_kernel_create(&init_net,
+                                           NETLINK_PSB_KOBJECT_UEVENT,
+                                           0x3, /* 3 is for hotplug & dpst */
+                                           NULL, NULL, THIS_MODULE);
+
+       if (!uevent_sock) {
+               printk(KERN_ERR "psb_kobject_uevent: failed create socket!\n");
+               return -ENODEV;
+       }
+       netlink_set_nonroot(NETLINK_PSB_KOBJECT_UEVENT, NL_NONROOT_RECV);
+
+       return 0;
+}
+
+#ifndef MODULE
+postcore_initcall(psb_kobject_uevent_init);
+#endif
+
+#endif
diff --git a/drivers/staging/mrst/drv/psb_umevents.c b/drivers/staging/mrst/drv/psb_umevents.c
new file mode 100644 (file)
index 0000000..c53699f
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+#include "psb_umevents.h"
+/**
+ * define sysfs operations supported by umevent objects.
+ *
+ */
+static struct sysfs_ops umevent_obj_sysfs_ops = {
+       .show = psb_umevent_attr_show,
+       .store = psb_umevent_attr_store,
+};
+/**
+ * define the data attributes we will expose through sysfs.
+ *
+ */
+static struct umevent_attribute data_0 =
+       __ATTR(data_0_val, 0666, psb_umevent_attr_show_imp,
+              psb_umevent_attr_store_imp);
+static struct umevent_attribute data_1 =
+       __ATTR(data_1_val, 0666, psb_umevent_attr_show_imp,
+              psb_umevent_attr_store_imp);
+static struct umevent_attribute data_2 =
+       __ATTR(data_2_val, 0666, psb_umevent_attr_show_imp,
+              psb_umevent_attr_store_imp);
+static struct umevent_attribute data_3 =
+       __ATTR(data_3_val, 0666, psb_umevent_attr_show_imp,
+              psb_umevent_attr_store_imp);
+static struct umevent_attribute data_4 =
+       __ATTR(data_4_val, 0666, psb_umevent_attr_show_imp,
+              psb_umevent_attr_store_imp);
+static struct umevent_attribute data_5 =
+       __ATTR(data_5_val, 0666, psb_umevent_attr_show_imp,
+              psb_umevent_attr_store_imp);
+static struct umevent_attribute data_6 =
+       __ATTR(data_6_val, 0666, psb_umevent_attr_show_imp,
+              psb_umevent_attr_store_imp);
+static struct umevent_attribute data_7 =
+       __ATTR(data_7_val, 0666, psb_umevent_attr_show_imp,
+              psb_umevent_attr_store_imp);
+/**
+ * define the structure used to seed our ktype.
+ *
+ */
+static struct attribute *umevent_obj_default_attrs[] = {
+       &data_0.attr,
+       &data_1.attr,
+       &data_2.attr,
+       &data_3.attr,
+       &data_4.attr,
+       &data_5.attr,
+       &data_6.attr,
+       &data_7.attr,
+       NULL,   /* need to NULL terminate the list of attributes */
+};
+/**
+ * specify the ktype for our kobjects.
+ *
+ */
+static struct kobj_type umevent_obj_ktype = {
+       .sysfs_ops = &umevent_obj_sysfs_ops,
+       .release = psb_umevent_obj_release,
+       .default_attrs = umevent_obj_default_attrs,
+};
+/**
+ * psb_umevent_attr_show - default kobject show function
+ *
+ * @kobj: kobject associated with the show operation
+ * @attr: attribute being requested
+ * @buf: pointer to the return buffer
+ *
+ */
+ssize_t psb_umevent_attr_show(struct kobject *kobj,
+                            struct attribute *attr,
+                            char *buf)
+{
+       struct umevent_attribute *attribute;
+       struct umevent_obj *any_umevent_obj;
+       attribute = to_umevent_attr(attr);
+       any_umevent_obj = to_umevent_obj(kobj);
+       if (!attribute->show)
+               return -EIO;
+
+       return attribute->show(any_umevent_obj, attribute, buf);
+}
+/**
+ * psb_umevent_attr_store - default kobject store function
+ *
+ * @kobj: kobject associated with the store operation
+ * @attr: attribute being requested
+ * @buf: input data to write to attribute
+ * @len: character count
+ *
+ */
+ssize_t psb_umevent_attr_store(struct kobject *kobj,
+                             struct attribute *attr,
+                             const char *buf, size_t len)
+{
+       struct umevent_attribute *attribute;
+       struct umevent_obj *any_umevent_obj;
+       attribute = to_umevent_attr(attr);
+       any_umevent_obj = to_umevent_obj(kobj);
+       if (!attribute->store)
+               return -EIO;
+
+       return attribute->store(any_umevent_obj, attribute, buf, len);
+}
+/**
+ * psb_umevent_obj_release - kobject release funtion
+ *
+ * @kobj: kobject to be released.
+ */
+void psb_umevent_obj_release(struct kobject *kobj)
+{
+       struct umevent_obj *any_umevent_obj;
+       any_umevent_obj = to_umevent_obj(kobj);
+       kfree(any_umevent_obj);
+}
+/**
+ *  psb_umevent_attr_show_imp - attribute show implementation
+ *
+ * @any_umevent_obj: kobject managed data to read from
+ * @attr: attribute being requested
+ * @buf: pointer to the return buffer
+ *
+ */
+ssize_t psb_umevent_attr_show_imp(struct umevent_obj
+                                    *any_umevent_obj,
+                                    struct umevent_attribute *attr,
+                                    char *buf)
+{
+       int var;
+
+       if (strcmp(attr->attr.name, "data_0_val") == 0)
+               var = any_umevent_obj->data_0_val;
+       else if (strcmp(attr->attr.name, "data_1_val") == 0)
+               var = any_umevent_obj->data_1_val;
+       else if (strcmp(attr->attr.name, "data_2_val") == 0)
+               var = any_umevent_obj->data_2_val;
+       else if (strcmp(attr->attr.name, "data_3_val") == 0)
+               var = any_umevent_obj->data_3_val;
+       else if (strcmp(attr->attr.name, "data_4_val") == 0)
+               var = any_umevent_obj->data_4_val;
+       else if (strcmp(attr->attr.name, "data_5_val") == 0)
+               var = any_umevent_obj->data_5_val;
+       else if (strcmp(attr->attr.name, "data_6_val") == 0)
+               var = any_umevent_obj->data_6_val;
+       else
+               var = any_umevent_obj->data_7_val;
+
+       return sprintf(buf, "%d\n", var);
+}
+/**
+ * psb_umevent_attr_store_imp - attribute store implementation
+ *
+ * @any_umevent_obj: kobject managed data to write to
+ * @attr: attribute being requested
+ * @buf: input data to write to attribute
+ * @count: character count
+ *
+ */
+ssize_t psb_umevent_attr_store_imp(struct umevent_obj
+                                     *any_umevent_obj,
+                                     struct umevent_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       int var;
+
+       sscanf(buf, "%du", &var);
+       if (strcmp(attr->attr.name, "data_0_val") == 0)
+               any_umevent_obj->data_0_val = var;
+       else if (strcmp(attr->attr.name, "data_1_val") == 0)
+               any_umevent_obj->data_1_val = var;
+       else if (strcmp(attr->attr.name, "data_2_val") == 0)
+               any_umevent_obj->data_2_val = var;
+       else if (strcmp(attr->attr.name, "data_3_val") == 0)
+               any_umevent_obj->data_3_val = var;
+       else if (strcmp(attr->attr.name, "data_4_val") == 0)
+               any_umevent_obj->data_4_val = var;
+       else if (strcmp(attr->attr.name, "data_5_val") == 0)
+               any_umevent_obj->data_5_val = var;
+       else if (strcmp(attr->attr.name, "data_6_val") == 0)
+               any_umevent_obj->data_6_val = var;
+       else
+               any_umevent_obj->data_7_val = var;
+       return count;
+}
+/**
+ * psb_create_umevent_obj - create and track new event objects
+ *
+ * @name: name to give to new sysfs / kobject entry
+ * @list: event object list to track the kobject in
+ */
+struct umevent_obj *psb_create_umevent_obj(const char *name,
+                                               struct umevent_list
+                                                       *list)
+{
+       struct umevent_obj *new_umevent_obj;
+       int retval;
+       new_umevent_obj = kzalloc(sizeof(*new_umevent_obj),
+                                      GFP_KERNEL);
+       if (!new_umevent_obj)
+               return NULL;
+
+       new_umevent_obj->kobj.kset = list->umevent_disp_pool;
+       retval = kobject_init_and_add(&new_umevent_obj->kobj,
+                                     &umevent_obj_ktype, NULL,
+                                     "%s", name);
+       if (retval) {
+               kobject_put(&new_umevent_obj->kobj);
+               return NULL;
+       }
+       psb_umevent_add_to_list(list, new_umevent_obj);
+       return new_umevent_obj;
+}
+/*EXPORT_SYMBOL(psb_create_umevent_obj); */
+/**
+ * psb_umevent_notify - info user mode of a new device
+ *
+ * @notify_disp_obj: event object to perform notification for
+ *
+ */
+void psb_umevent_notify(struct umevent_obj *notify_disp_obj)
+{
+       kobject_uevent(&notify_disp_obj->kobj, KOBJ_ADD);
+}
+/*EXPORT_SYMBOL(psb_umevent_notify); */
+
+void psb_umevent_notify_gfxsock(struct umevent_obj *notify_disp_obj,
+                               int dst_group_id)
+{
+       psb_kobject_uevent(&notify_disp_obj->kobj, KOBJ_ADD, dst_group_id);
+}
+/*EXPORT_SYMBOL(psb_umevent_notify_gfxsock);*/
+/**
+ * psb_umevent_notify_change - notify user mode of a change to a device
+ *
+ * @notify_disp_obj: event object to perform notification for
+ *
+ */
+void psb_umevent_notify_change(struct umevent_obj *notify_disp_obj)
+{
+       kobject_uevent(&notify_disp_obj->kobj, KOBJ_CHANGE);
+}
+/*EXPORT_SYMBOL(psb_umevent_notify_change); */
+/**
+ * psb_umevent_notify_change - notify user mode of a change to a device
+ *
+ * @notify_disp_obj: event object to perform notification for
+ *
+ */
+void psb_umevent_notify_change_gfxsock(struct umevent_obj *notify_disp_obj,
+                                       int dst_group_id)
+{
+       psb_kobject_uevent(&notify_disp_obj->kobj, KOBJ_CHANGE, dst_group_id);
+}
+/*EXPORT_SYMBOL(psb_umevent_notify_change_gfxsock); */
+/**
+ * psb_destroy_umvent_obj - decrement ref count on event so kernel can kill it
+ *
+ * @any_umevent_obj: event object to destroy
+ *
+ */
+static void psb_destroy_umevent_obj(struct umevent_obj
+                                    *any_umevent_obj)
+{
+       kobject_put(&any_umevent_obj->kobj);
+}
+/**
+ *
+ * psb_umevent_init - init the event pool
+ *
+ * @parent_kobj: parent kobject to associate new kset with
+ * @new_umevent_list: event list to associate kset with
+ * @name: name to give to new sysfs entry
+ *
+ */
+int psb_umevent_init(struct kobject *parent_kobj,
+                    struct umevent_list *new_umevent_list,
+                    const char *name)
+{
+       psb_umevent_init_list(new_umevent_list);
+       new_umevent_list->umevent_disp_pool = kset_create_and_add(name, NULL,
+                                                    parent_kobj);
+       if (!new_umevent_list->umevent_disp_pool)
+               return -ENOMEM;
+
+       return 0;
+}
+/*EXPORT_SYMBOL(psb_umevent_init); */
+/**
+ *
+ * psb_umevent_cleanup - cleanup all event objects
+ *
+ * @kill_list: list of events to destroy
+ *
+ */
+void psb_umevent_cleanup(struct umevent_list *kill_list)
+{
+       psb_umevent_destroy_list(kill_list);
+}
+/*EXPORT_SYMBOL(psb_umevent_cleanup); */
+/**
+ * psb_umevent_add_to_list - add an event to the event list
+ *
+ * @list: list to add the event to
+ * @umevent_obj_to_add: event to add
+ *
+ */
+void psb_umevent_add_to_list(struct umevent_list *list,
+                             struct umevent_obj *umevent_obj_to_add)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&list->list_lock, flags);
+       list_add(&umevent_obj_to_add->head, &list->head);
+       spin_unlock_irqrestore(&list->list_lock, flags);
+}
+/**
+ * psb_umevent_init_list - initialize event list
+ *
+ * @list: list to initialize
+ *
+ */
+void psb_umevent_init_list(struct umevent_list *list)
+{
+       spin_lock_init(&list->list_lock);
+       INIT_LIST_HEAD(&list->head);
+}
+/**
+ * psb_umevent_create_list - allocate an event list
+ *
+ */
+struct umevent_list *psb_umevent_create_list(void)
+{
+       struct umevent_list *new_umevent_list;
+       new_umevent_list = NULL;
+       new_umevent_list =  kmalloc(sizeof(struct umevent_list),
+                                        GFP_ATOMIC);
+       return new_umevent_list;
+}
+/*EXPORT_SYMBOL(psb_umevent_create_list); */
+/**
+ * psb_umevent_destroy_list - destroy a list and clean up all mem
+ *
+ * @list: list to destroy and clean up after
+ *
+ */
+void psb_umevent_destroy_list(struct umevent_list *list)
+{
+       struct umevent_obj *umevent_obj_curr;
+       struct list_head *node;
+       struct list_head *node_kill;
+       int i;
+       i = 0;
+       node = NULL;
+       node_kill = NULL;
+       node = list->head.next;
+       while (node != (&list->head)) {
+               umevent_obj_curr = list_entry(node,
+                               struct umevent_obj,
+                                                  head);
+               node_kill = node;
+               node = umevent_obj_curr->head.next;
+               list_del(node_kill);
+               psb_destroy_umevent_obj(umevent_obj_curr);
+               umevent_obj_curr = NULL;
+               i++;
+       }
+       kset_unregister(list->umevent_disp_pool);
+       kfree(list);
+}
+/**
+ * psb_umevent_remove_from_list - remove an event from tracking list
+ *
+ * @list: list to remove the event from
+ * @disp_to_remove: name of event to remove.
+ *
+ */
+void psb_umevent_remove_from_list(struct umevent_list *list,
+                                  const char *disp_to_remove)
+{
+       struct umevent_obj *umevent_obj_curr = NULL;
+       struct list_head *node = NULL;
+       struct list_head *node_kill = NULL;
+       int i = 0;
+       int found_match = 0;
+       i = 0;
+       node = NULL;
+       node_kill = NULL;
+       node = list->head.next;
+       while (node != (&list->head)) {
+               umevent_obj_curr = list_entry(node,
+                               struct umevent_obj, head);
+               if (strcmp(umevent_obj_curr->kobj.name,
+                         disp_to_remove) == 0) {
+                       found_match = 1;
+                       break;
+               }
+               node = NULL;
+               node = umevent_obj_curr->head.next;
+               i++;
+       }
+       if (found_match == 1) {
+               node_kill = node;
+               node = umevent_obj_curr->head.next;
+               list_del(node_kill);
+               psb_destroy_umevent_obj(umevent_obj_curr);
+               umevent_obj_curr = NULL;
+       }
+}
+/*EXPORT_SYMBOL(psb_umevent_remove_from_list); */
+/**
+ * psb_umevent_find_obj - find an event in a tracking list
+ *
+ * @name: name of the event to find
+ * @list: list to find the event in
+ *
+ */
+struct umevent_obj *psb_umevent_find_obj(const char *name,
+                                 struct umevent_list *list)
+{
+       struct umevent_obj *umevent_obj_curr = NULL;
+       struct list_head *node = NULL;
+       struct list_head *node_find = NULL;
+       int i = 0;
+       int found_match = 0;
+       i = 0;
+       node = NULL;
+       node_find = NULL;
+       node = list->head.next;
+       while (node != (&list->head)) {
+               umevent_obj_curr = list_entry(node,
+                               struct umevent_obj, head);
+               if (strcmp(umevent_obj_curr->kobj.name,
+                         name) == 0) {
+                       found_match = 1;
+                       break;
+               }
+               node = NULL;
+               node = umevent_obj_curr->head.next;
+               i++;
+       }
+       if (found_match == 1)
+               return umevent_obj_curr;
+
+       return NULL;
+}
+/*EXPORT_SYMBOL(psb_umevent_find_obj); */
+/**
+ * psb_umevent_debug_dump_list - debug list dump
+ *
+ * @list: list to dump
+ *
+ */
+void psb_umevent_debug_dump_list(struct umevent_list *list)
+{
+       struct umevent_obj *umevent_obj_curr;
+       unsigned long flags;
+       struct list_head *node;
+       int i;
+       spin_lock_irqsave(&list->list_lock, flags);
+       i = 0;
+       node = NULL;
+       node = list->head.next;
+       while (node != (&list->head)) {
+               umevent_obj_curr = list_entry(node,
+                                                  struct umevent_obj,
+                                                  head);
+               /*TBD: DUMP ANY REQUIRED VALUES WITH PRINTK*/
+               node = NULL;
+               node = umevent_obj_curr->head.next;
+               i++;
+       }
+       spin_unlock_irqrestore(&list->list_lock, flags);
+}
diff --git a/drivers/staging/mrst/drv/psb_umevents.h b/drivers/staging/mrst/drv/psb_umevents.h
new file mode 100644 (file)
index 0000000..80651a2
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+#ifndef _PSB_UMEVENT_H_
+#define _PSB_UMEVENT_H_
+/**
+ * required includes
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <drm/drmP.h>
+#include <drm/drm_core.h>
+#include <drm/drm_pciids.h>
+#include <linux/spinlock.h>
+/**
+ * event groups for routing to different user mode threads
+ *
+ */
+#define DRM_DPST_SOCKET_GROUP_ID 1
+#define DRM_HOTPLUG_SOCKET_GROUP_ID 2
+#define DRM_HDMI_AUDIO_SOCKET_GROUP 4
+#define DRM_HDMI_HDCP_SOCKET_GROUP 8
+#define DRM_GFX_SOCKET_GROUPS 15
+/**
+ * event structure managed by kobjects
+ *
+ */
+struct umevent_obj {
+       struct kobject kobj;
+       struct list_head head;
+       int data_0_val;
+       int data_1_val;
+       int data_2_val;
+       int data_3_val;
+       int data_4_val;
+       int data_5_val;
+       int data_6_val;
+       int data_7_val;
+};
+/**
+ * event tracking list element
+ *
+ */
+struct umevent_list{
+       struct list_head head;
+       struct kset *umevent_disp_pool;
+       spinlock_t list_lock;
+};
+/**
+ * to go back and forth between kobjects and their main container
+ *
+ */
+#define to_umevent_obj(x) \
+       container_of(x, struct umevent_obj, kobj)
+
+/**
+ * event attributes exposed via sysfs
+ *
+ */
+struct umevent_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct umevent_obj *any_umevent_obj,
+                       struct umevent_attribute *attr, char *buf);
+       ssize_t (*store)(struct umevent_obj *any_umevent_obj,
+                        struct umevent_attribute *attr,
+                        const char *buf, size_t count);
+};
+/**
+ * to go back and forth between the attribute passed to us by the OS
+ * and the umevent_attribute
+ *
+ */
+#define to_umevent_attr(x) \
+       container_of(x, struct umevent_attribute, \
+       attr)
+
+/**
+ * umevent function prototypes
+ *
+ */
+extern struct umevent_obj *psb_create_umevent_obj(const char *name,
+                                               struct umevent_list
+                                                       *list);
+extern ssize_t psb_umevent_attr_show(struct kobject *kobj,
+                                     struct attribute *attr, char *buf);
+extern ssize_t psb_umevent_attr_store(struct kobject *kobj,
+                                      struct attribute *attr,
+                                      const char *buf, size_t len);
+extern ssize_t psb_umevent_attr_show_imp(struct umevent_obj
+                                    *any_umevent_obj,
+                                    struct umevent_attribute *attr,
+                                    char *buf);
+extern ssize_t psb_umevent_attr_store_imp(struct umevent_obj
+                                     *any_umevent_obj,
+                                     struct umevent_attribute *attr,
+                                     const char *buf, size_t count);
+extern void psb_umevent_cleanup(struct umevent_list *kill_list);
+extern int psb_umevent_init(struct kobject *parent_kobj,
+                           struct umevent_list *new_umevent_list,
+                           const char *name);
+extern void psb_umevent_init_list(struct umevent_list *list);
+extern void psb_umevent_debug_dump_list(struct umevent_list *list);
+extern void psb_umevent_add_to_list(struct umevent_list *list,
+                                    struct umevent_obj
+                                    *umevent_obj_to_add);
+extern void psb_umevent_destroy_list(struct umevent_list *list);
+extern struct umevent_list *psb_umevent_create_list(void);
+extern void psb_umevent_notify(struct umevent_obj *notify_disp_obj);
+extern void psb_umevent_notify_gfxsock(struct umevent_obj *notify_disp_obj,
+                                       int dst_group_id);
+extern void psb_umevent_obj_release(struct kobject *kobj);
+extern void psb_umevent_remove_from_list(struct umevent_list *list,
+                                         const char *disp_to_remove);
+extern void psb_umevent_workqueue_dispatch(int work_type, const char *name,
+                                      struct umevent_list *list);
+extern void psb_umevent_notify_change(struct umevent_obj *notify_disp_obj);
+extern void psb_umevent_notify_change_gfxsock(struct umevent_obj
+                                             *notify_disp_obj,
+                                             int dst_group_id);
+extern struct umevent_obj *psb_umevent_find_obj(const char *name,
+                                               struct umevent_list
+                                                       *list);
+/**
+ * socket function prototypes
+ *
+ */
+extern int psb_kobject_uevent(struct kobject *kobj,
+                             enum kobject_action action, int dst_group_id);
+extern int psb_kobject_uevent_env(struct kobject *kobj,
+                                 enum kobject_action action,
+                                 char *envp[], int dst_group_id);
+int psb_add_uevent_var(struct kobj_uevent_env *env,
+                      const char *format, ...)
+       __attribute__((format (printf, 2, 3)));
+int psb_kobject_action_type(const char *buf,
+                           size_t count, enum kobject_action *type);
+
+#if defined(CONFIG_NET)
+int psb_kobject_uevent_init(void);
+#endif
+
+#endif
diff --git a/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c b/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c
new file mode 100644 (file)
index 0000000..7a65407
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+ * Copyright Â© 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "tc35876x-dsi-lvds.h"
+
+static struct i2c_client *tc35876x_client;
+
+/* GPIO pins. FIXME: Get these from platform data (firmware) */
+#define GPIO_MIPI_BRIDGE_RESET 115
+#define GPIO_MIPI_PANEL_RESET  128
+#define GPIO_MIPI_LCD_STBYB    173
+#define GPIO_MIPI_LCD_BIAS_EN  108
+#define GPIO_MIPI_LCD_VADD     110
+
+#define FLD_MASK(start, end)   (((1 << ((start) - (end) + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
+
+/* DSI D-PHY Layer Registers */
+#define D0W_DPHYCONTTX         0x0004
+#define CLW_DPHYCONTRX         0x0020
+#define D0W_DPHYCONTRX         0x0024
+#define D1W_DPHYCONTRX         0x0028
+#define D2W_DPHYCONTRX         0x002C
+#define D3W_DPHYCONTRX         0x0030
+#define COM_DPHYCONTRX         0x0038
+#define CLW_CNTRL              0x0040
+#define D0W_CNTRL              0x0044
+#define D1W_CNTRL              0x0048
+#define D2W_CNTRL              0x004C
+#define D3W_CNTRL              0x0050
+#define DFTMODE_CNTRL          0x0054
+
+/* DSI PPI Layer Registers */
+#define PPI_STARTPPI           0x0104
+#define PPI_BUSYPPI            0x0108
+#define PPI_LINEINITCNT                0x0110
+#define PPI_LPTXTIMECNT                0x0114
+#define PPI_LANEENABLE         0x0134
+#define PPI_TX_RX_TA           0x013C
+#define PPI_CLS_ATMR           0x0140
+#define PPI_D0S_ATMR           0x0144
+#define PPI_D1S_ATMR           0x0148
+#define PPI_D2S_ATMR           0x014C
+#define PPI_D3S_ATMR           0x0150
+#define PPI_D0S_CLRSIPOCOUNT   0x0164
+#define PPI_D1S_CLRSIPOCOUNT   0x0168
+#define PPI_D2S_CLRSIPOCOUNT   0x016C
+#define PPI_D3S_CLRSIPOCOUNT   0x0170
+#define CLS_PRE                        0x0180
+#define D0S_PRE                        0x0184
+#define D1S_PRE                        0x0188
+#define D2S_PRE                        0x018C
+#define D3S_PRE                        0x0190
+#define CLS_PREP               0x01A0
+#define D0S_PREP               0x01A4
+#define D1S_PREP               0x01A8
+#define D2S_PREP               0x01AC
+#define D3S_PREP               0x01B0
+#define CLS_ZERO               0x01C0
+#define D0S_ZERO               0x01C4
+#define D1S_ZERO               0x01C8
+#define D2S_ZERO               0x01CC
+#define D3S_ZERO               0x01D0
+#define PPI_CLRFLG             0x01E0
+#define PPI_CLRSIPO            0x01E4
+#define HSTIMEOUT              0x01F0
+#define HSTIMEOUTENABLE                0x01F4
+
+/* DSI Protocol Layer Registers */
+#define DSI_STARTDSI           0x0204
+#define DSI_BUSYDSI            0x0208
+#define DSI_LANEENABLE         0x0210
+#define DSI_LANESTATUS0                0x0214
+#define DSI_LANESTATUS1                0x0218
+#define DSI_INTSTATUS          0x0220
+#define DSI_INTMASK            0x0224
+#define DSI_INTCLR             0x0228
+#define DSI_LPTXTO             0x0230
+
+/* DSI General Registers */
+#define DSIERRCNT              0x0300
+
+/* DSI Application Layer Registers */
+#define APLCTRL                        0x0400
+#define RDPKTLN                        0x0404
+
+/* Video Path Registers */
+#define VPCTRL                 0x0450
+#define HTIM1                  0x0454
+#define HTIM2                  0x0458
+#define VTIM1                  0x045C
+#define VTIM2                  0x0460
+#define VFUEN                  0x0464
+
+/* LVDS Registers */
+#define LVMX0003               0x0480
+#define LVMX0407               0x0484
+#define LVMX0811               0x0488
+#define LVMX1215               0x048C
+#define LVMX1619               0x0490
+#define LVMX2023               0x0494
+#define LVMX2427               0x0498
+#define LVCFG                  0x049C
+#define LVPHY0                 0x04A0
+#define LVPHY1                 0x04A4
+
+/* System Registers */
+#define SYSSTAT                        0x0500
+#define SYSRST                 0x0504
+
+/* GPIO Registers */
+#define GPIOC                  0x0520
+#define GPIOO                  0x0524
+#define GPIOI                  0x0528
+
+/* I2C Registers */
+#define I2CTIMCTRL             0x0540
+#define I2CMADDR               0x0544
+#define WDATAQ                 0x0548
+#define RDATAQ                 0x054C
+
+/* Chip/Rev Registers */
+#define IDREG                  0x0580
+
+/* Debug Registers */
+#define DEBUG00                        0x05A0
+#define DEBUG01                        0x05A4
+
+/* Input muxing for registers LVMX0003...LVMX2427 */
+enum {
+       INPUT_R0,       /* 0 */
+       INPUT_R1,
+       INPUT_R2,
+       INPUT_R3,
+       INPUT_R4,
+       INPUT_R5,
+       INPUT_R6,
+       INPUT_R7,
+       INPUT_G0,       /* 8 */
+       INPUT_G1,
+       INPUT_G2,
+       INPUT_G3,
+       INPUT_G4,
+       INPUT_G5,
+       INPUT_G6,
+       INPUT_G7,
+       INPUT_B0,       /* 16 */
+       INPUT_B1,
+       INPUT_B2,
+       INPUT_B3,
+       INPUT_B4,
+       INPUT_B5,
+       INPUT_B6,
+       INPUT_B7,
+       INPUT_HSYNC,    /* 24 */
+       INPUT_VSYNC,
+       INPUT_DE,
+       LOGIC_0,
+       /* 28...31 undefined */
+};
+
+#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00)              \
+       (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) |    \
+       FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
+
+/**
+ * tc35876x_regw - Write DSI-LVDS bridge register using I2C
+ * @client: struct i2c_client to use
+ * @reg: register address
+ * @value: value to write
+ *
+ * Returns 0 on success, or a negative error value.
+ */
+static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
+{
+       int r;
+       u8 tx_data[] = {
+               /* NOTE: Register address big-endian, data little-endian. */
+               (reg >> 8) & 0xff,
+               reg & 0xff,
+               value & 0xff,
+               (value >> 8) & 0xff,
+               (value >> 16) & 0xff,
+               (value >> 24) & 0xff,
+       };
+       struct i2c_msg msgs[] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .buf = tx_data,
+                       .len = ARRAY_SIZE(tx_data),
+               },
+       };
+
+       r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (r < 0) {
+               dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
+                       __func__, reg, value, r);
+               return r;
+       }
+
+       if (r < ARRAY_SIZE(msgs)) {
+               dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
+                       __func__, reg, value, r);
+               return -EAGAIN;
+       }
+
+       dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n", __func__, reg,
+               value);
+
+       return 0;
+}
+
+/**
+ * tc35876x_regr - Read DSI-LVDS bridge register using I2C
+ * @client: struct i2c_client to use
+ * @reg: register address
+ * @value: pointer for storing the value
+ *
+ * Returns 0 on success, or a negative error value.
+ */
+static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
+{
+       int r;
+       u8 tx_data[] = {
+               (reg >> 8) & 0xff,
+               reg & 0xff,
+       };
+       u8 rx_data[4];
+       struct i2c_msg msgs[] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .buf = tx_data,
+                       .len = ARRAY_SIZE(tx_data),
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .buf = rx_data,
+                       .len = ARRAY_SIZE(rx_data),
+                },
+       };
+
+       r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (r < 0) {
+               dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
+                       reg, r);
+               return r;
+       }
+
+       if (r < ARRAY_SIZE(msgs)) {
+               dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
+                       reg, r);
+               return -EAGAIN;
+       }
+
+       *value = rx_data[0] << 24 | rx_data[1] << 16 |
+               rx_data[2] << 8 | rx_data[3];
+
+       dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
+               reg, *value);
+
+       return 0;
+}
+
+void tc35876x_set_bridge_reset_state(int state)
+{
+       WARN_ON(!tc35876x_client);
+       dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
+
+       if (state) {
+               gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);
+               mdelay(10);
+       } else {
+               /* Pull MIPI Bridge reset pin to Low */
+               gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);
+               mdelay(20);
+               /* Pull MIPI Bridge reset pin to High */
+               gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 1);
+               mdelay(40);
+       }
+}
+
+void tc35876x_configure_lvds_bridge(struct drm_device *dev)
+{
+       struct i2c_client *i2c = tc35876x_client;
+       u32 ppi_lptxtimecnt;
+       u32 txtagocnt;
+       u32 txtasurecnt;
+       u32 id;
+
+       WARN_ON(!tc35876x_client);
+       dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
+
+       tc35876x_regr(i2c, IDREG, &id);
+       dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
+
+       ppi_lptxtimecnt = 4;
+       txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
+       txtasurecnt = 3 * ppi_lptxtimecnt / 2;
+       tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
+               FLD_VAL(txtasurecnt, 10, 0));
+       tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
+
+       tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
+       tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
+       tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
+       tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
+
+       /* Enabling MIPI & PPI lanes, Enable 4 lanes */
+       tc35876x_regw(i2c, PPI_LANEENABLE,
+               BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
+       tc35876x_regw(i2c, DSI_LANEENABLE,
+               BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
+       tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
+       tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
+
+       /* Setting LVDS output frequency */
+       tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
+               FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
+
+       /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
+       tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
+
+       /* Horizontal back porch and horizontal pulse width. 0x00280028 */
+       tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
+
+       /* Horizontal front porch and horizontal active video size. 0x00500500*/
+       tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
+
+       /* Vertical back porch and vertical sync pulse width. 0x000e000a */
+       tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
+
+       /* Vertical front porch and vertical display size. 0x000e0320 */
+       tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
+
+       /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
+       tc35876x_regw(i2c, VFUEN, BIT(0));
+
+       /* LVDS-TX input muxing */
+       tc35876x_regw(i2c, LVMX0003, /* 0x03020100 */
+               INPUT_MUX(INPUT_R3, INPUT_R2, INPUT_R1, INPUT_R0));
+       tc35876x_regw(i2c, LVMX0407, /* 0x08050704 */
+               INPUT_MUX(INPUT_G0, INPUT_R5, INPUT_R7, INPUT_R4));
+       tc35876x_regw(i2c, LVMX0811, /* 0x0F0E0A09 */
+               INPUT_MUX(INPUT_G7, INPUT_G6, INPUT_G2, INPUT_G1));
+       tc35876x_regw(i2c, LVMX1215, /* 0x100D0C0B */
+               INPUT_MUX(INPUT_B0, INPUT_G5, INPUT_G4, INPUT_G3));
+       tc35876x_regw(i2c, LVMX1619, /* 0x12111716 */
+               INPUT_MUX(INPUT_B2, INPUT_B1, INPUT_B7, INPUT_B6));
+       tc35876x_regw(i2c, LVMX2023, /* 0x1B151413 */
+               INPUT_MUX(LOGIC_0, INPUT_B5, INPUT_B4, INPUT_B3));
+       tc35876x_regw(i2c, LVMX2427, /* 0x061A1918 */
+               INPUT_MUX(INPUT_R6, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
+
+       /* Enable LVDS transmitter. */
+       tc35876x_regw(i2c, LVCFG, BIT(0));
+
+       /* Clear notifications. Don't write reserved bits. Was write 0xffffffff
+        * to 0x0288, must be in error?! */
+       tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
+}
+
+void tc35876x_toshiba_bridge_panel_off(void)
+{
+       WARN_ON(!tc35876x_client);
+       dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
+
+       gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 0);
+       mdelay(1);
+
+       gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 0);
+       mdelay(1);
+}
+
+void tc35876x_toshiba_bridge_panel_on(void)
+{
+       WARN_ON(!tc35876x_client);
+       dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
+
+       gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 0);
+       gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 0);
+       gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 0);
+       gpio_set_value_cansleep(GPIO_MIPI_LCD_BIAS_EN, 0);
+       mdelay(10);
+
+       gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 1);
+       mdelay(10);
+
+       gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 1);
+       mdelay(50);
+
+       gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 1);
+       mdelay(100);
+
+       gpio_set_value_cansleep(GPIO_MIPI_LCD_BIAS_EN, 1);
+}
+
+void tc35876x_bridge_get_display_params(struct drm_display_mode *mode)
+{
+       WARN_ON(!tc35876x_client);
+       dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
+
+       /* FIXME: do this properly. */
+       mode->hdisplay = 1280;
+       mode->vdisplay = 800;
+       mode->hsync_start = 1360;
+       mode->hsync_end = 1400;
+       mode->htotal = 1440;
+       mode->vsync_start = 814;
+       mode->vsync_end = 824;
+       mode->vtotal = 838;
+       mode->clock = 33324;
+
+       dev_info(&tc35876x_client->dev, "hdisplay(w) = %d\n", mode->hdisplay);
+       dev_info(&tc35876x_client->dev, "vdisplay(h) = %d\n", mode->vdisplay);
+       dev_info(&tc35876x_client->dev, "HSS = %d\n", mode->hsync_start);
+       dev_info(&tc35876x_client->dev, "HSE = %d\n", mode->hsync_end);
+       dev_info(&tc35876x_client->dev, "htotal = %d\n", mode->htotal);
+       dev_info(&tc35876x_client->dev, "VSS = %d\n", mode->vsync_start);
+       dev_info(&tc35876x_client->dev, "VSE = %d\n", mode->vsync_end);
+       dev_info(&tc35876x_client->dev, "vtotal = %d\n", mode->vtotal);
+       dev_info(&tc35876x_client->dev, "clock = %d\n", mode->clock);
+}
+
+static int tc35876x_bridge_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       dev_info(&client->dev, "%s\n", __func__);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       /* FIXME: get GPIOs from platform data, check for errors. */
+       gpio_request(GPIO_MIPI_BRIDGE_RESET, "tc35876x bridge reset");
+       gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 0);
+
+       gpio_request(GPIO_MIPI_PANEL_RESET, "tc35876x panel reset");
+       gpio_direction_output(GPIO_MIPI_PANEL_RESET, 0);
+
+       gpio_request(GPIO_MIPI_LCD_STBYB, "tc35876x lcd stbyb");
+       gpio_direction_output(GPIO_MIPI_LCD_STBYB, 0);
+
+       gpio_request(GPIO_MIPI_LCD_BIAS_EN, "tc35876x lcd bias en");
+       gpio_direction_output(GPIO_MIPI_LCD_BIAS_EN, 0);
+
+       gpio_request(GPIO_MIPI_LCD_VADD, "tc35876x lcd vadd");
+       gpio_direction_output(GPIO_MIPI_LCD_VADD, 0);
+
+       tc35876x_client = client;
+
+       return 0;
+}
+
+static int tc35876x_bridge_remove(struct i2c_client *client)
+{
+       dev_dbg(&client->dev, "%s\n", __func__);
+
+       gpio_free(GPIO_MIPI_BRIDGE_RESET);
+       gpio_free(GPIO_MIPI_PANEL_RESET);
+       gpio_free(GPIO_MIPI_LCD_STBYB);
+       gpio_free(GPIO_MIPI_LCD_BIAS_EN);
+       gpio_free(GPIO_MIPI_LCD_VADD);
+
+       tc35876x_client = NULL;
+
+       return 0;
+}
+
+static const struct i2c_device_id tc35876x_bridge_id[] = {
+       { "tc35876x", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
+
+static struct i2c_driver tc35876x_bridge_i2c_driver = {
+       .driver = {
+               .name = "tc35876x",
+       },
+       .id_table = tc35876x_bridge_id,
+       .probe = tc35876x_bridge_probe,
+       .remove = __devexit_p(tc35876x_bridge_remove),
+};
+
+#if 1
+#define TC35876X_I2C_ADAPTER   2
+#define TC35876X_I2C_ADDR      0x0f
+
+/* HACK to create I2C device while it's not created by platform code */
+static int __init tc35876x_hack_create_device(void)
+{
+       struct i2c_adapter *adapter;
+       struct i2c_client *client;
+       struct i2c_board_info info = {
+               .type = "tc35876x",
+               .addr = TC35876X_I2C_ADDR,
+       };
+
+       pr_debug("%s\n", __func__);
+
+       adapter = i2c_get_adapter(TC35876X_I2C_ADAPTER);
+       if (!adapter) {
+               pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
+                       TC35876X_I2C_ADAPTER);
+               return -EINVAL;
+       }
+
+       client = i2c_new_device(adapter, &info);
+       if (!client) {
+               pr_err("%s: i2c_new_device() failed\n", __func__);
+               i2c_put_adapter(adapter);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+#else
+static inline int __init tc35876x_hack_create_device(void)
+{
+       return 0;
+}
+#endif
+
+int tc35876x_bridge_init(void)
+{
+       int r;
+
+       pr_debug("%s\n", __func__);
+
+       r = tc35876x_hack_create_device();
+       if (r)
+               return r;
+
+       return i2c_add_driver(&tc35876x_bridge_i2c_driver);
+}
+
+void tc35876x_bridge_exit(void)
+{
+       pr_debug("%s\n", __func__);
+
+       i2c_del_driver(&tc35876x_bridge_i2c_driver);
+}
diff --git a/drivers/staging/mrst/drv/tc35876x-dsi-lvds.h b/drivers/staging/mrst/drv/tc35876x-dsi-lvds.h
new file mode 100644 (file)
index 0000000..6b0e700
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright Â© 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __MDFLD_DSI_LVDS_BRIDGE_H__
+#define __MDFLD_DSI_LVDS_BRIDGE_H__
+
+void tc35876x_set_bridge_reset_state(int state);
+void tc35876x_configure_lvds_bridge(struct drm_device *dev);
+void tc35876x_toshiba_bridge_panel_off(void);
+void tc35876x_toshiba_bridge_panel_on(void);
+void tc35876x_bridge_get_display_params(struct drm_display_mode *mode);
+int tc35876x_bridge_init(void);
+void tc35876x_bridge_exit(void);
+
+#endif /*__MDFLD_DSI_LVDS_BRIDGE_H__*/
diff --git a/drivers/staging/mrst/drv/tmd_vid.c b/drivers/staging/mrst/drv/tmd_vid.c
new file mode 100644 (file)
index 0000000..2ac1da0
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jim Liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ * Gideon Eaton <eaton.
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#include "displays/tmd_vid.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "tc35876x-dsi-lvds.h"
+
+static struct drm_display_mode*
+tmd_vid_get_config_mode(struct drm_device* dev)
+{
+       struct drm_display_mode *mode;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+       bool use_gct = false; /*Disable GCT for now*/
+
+       PSB_DEBUG_ENTRY("\n");
+
+       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+       if (!mode)
+               return NULL;
+
+       if (get_panel_type(dev, 0) == TC35876X) { /* FIXME: pipe */
+               tc35876x_bridge_get_display_params(mode);
+       } else if (use_gct) {
+               PSB_DEBUG_ENTRY("gct find MIPI panel. \n");
+
+               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+               mode->hsync_start = mode->hdisplay + \
+                               ((ti->hsync_offset_hi << 8) | \
+                               ti->hsync_offset_lo);
+               mode->hsync_end = mode->hsync_start + \
+                               ((ti->hsync_pulse_width_hi << 8) | \
+                               ti->hsync_pulse_width_lo);
+               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+                                                               ti->hblank_lo);
+               mode->vsync_start = \
+                       mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+                                               ti->vsync_offset_lo);
+               mode->vsync_end = \
+                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+                                               ti->vsync_pulse_width_lo);
+               mode->vtotal = mode->vdisplay + \
+                               ((ti->vblank_hi << 8) | ti->vblank_lo);
+               mode->clock = ti->pixel_clock * 10;
+
+               PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay);
+               PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay);
+               PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start);
+               PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end);
+               PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal);
+               PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start);
+               PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end);
+               PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal);
+               PSB_DEBUG_ENTRY("clock is %d\n", mode->clock);
+       } else {
+               mode->hdisplay = 480;
+               mode->vdisplay = 854;
+               mode->hsync_start = 487;
+               mode->hsync_end = 490;
+               mode->htotal = 499;
+               mode->vsync_start = 861;
+               mode->vsync_end = 865;
+               mode->vtotal = 873;
+               mode->clock = 33264;
+       }
+
+       drm_mode_set_name(mode);
+       drm_mode_set_crtcinfo(mode, 0);
+       
+       mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+       return mode;
+}
+
+static int tmd_vid_get_panel_info(struct drm_device * dev,
+                               int pipe,
+                               struct panel_info * pi)
+{
+       if(!dev || !pi)
+               return -EINVAL;
+
+       pi->width_mm = TMD_PANEL_WIDTH;
+       pi->height_mm = TMD_PANEL_HEIGHT;
+
+       return 0;
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: mdfld_init_TMD_MIPI
+ *
+ * DESCRIPTION:  This function is called only by mrst_dsi_mode_set and
+ *               restore_display_registers.  since this function does not
+ *               acquire the mutex, it is important that the calling function
+ *               does!
+\* ************************************************************************* */
+
+/* FIXME: make the below data u8 instead of u32; note byte order! */
+static u32 tmd_cmd_mcap_off[] = {0x000000b2};
+static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
+static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
+static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef};
+static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef};
+static u32 tmd_cmd_set_mode[] = {0x000000b3};
+static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
+static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df};
+static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055};
+static u32 tmd_cmd_set_video_mode[] = {0x00000153};
+/*no auto_bl,need add in furture*/
+static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};
+static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
+
+static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
+                                     int pipe)
+{
+       struct mdfld_dsi_pkg_sender *sender
+                       = mdfld_dsi_get_pkg_sender(dsi_config);
+
+       DRM_INFO("Enter mdfld init TMD MIPI display.\n");
+
+       if (!sender) {
+               DRM_ERROR("Cannot get sender\n");
+               return;
+       }
+
+       if (dsi_config->dvr_ic_inited)
+               return;
+
+       msleep(3);
+
+       /* FIXME: make the below data u8 instead of u32; note byte order! */
+
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_mcap_off,
+                               sizeof(tmd_cmd_mcap_off), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_lane_switch,
+                               sizeof(tmd_cmd_enable_lane_switch), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_lane_num,
+                               sizeof(tmd_cmd_set_lane_num), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock0,
+                               sizeof(tmd_cmd_pushing_clock0), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock1,
+                               sizeof(tmd_cmd_pushing_clock1), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_mode,
+                               sizeof(tmd_cmd_set_mode), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_sync_pulse_mode,
+                               sizeof(tmd_cmd_set_sync_pulse_mode), false);
+       mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_column,
+                               sizeof(tmd_cmd_set_column), false);
+       mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_page,
+                               sizeof(tmd_cmd_set_page), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_video_mode,
+                               sizeof(tmd_cmd_set_video_mode), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_backlight,
+                               sizeof(tmd_cmd_enable_backlight), false);
+       mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_backlight_dimming,
+                               sizeof(tmd_cmd_set_backlight_dimming), false);
+
+       dsi_config->dvr_ic_inited = 1;
+}
+
+/*TPO DPI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_tpo_dpi_encoder_helper_funcs = {
+       .dpms = mdfld_dsi_dpi_dpms,
+       .mode_fixup = mdfld_dsi_dpi_mode_fixup,
+       .prepare = mdfld_dsi_dpi_prepare,
+       .mode_set = mdfld_dsi_dpi_mode_set,
+       .commit = mdfld_dsi_dpi_commit,
+};
+
+/*TPO DPI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+void tmd_vid_init(struct drm_device* dev, struct panel_funcs* p_funcs)
+{
+       if(!dev || !p_funcs) {
+               DRM_ERROR("Invalid parameters\n");
+               return;
+       }
+       
+       PSB_DEBUG_ENTRY("\n");
+       
+       p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
+       p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
+       p_funcs->get_config_mode = &tmd_vid_get_config_mode;
+       p_funcs->update_fb = NULL;
+       p_funcs->get_panel_info = tmd_vid_get_panel_info;
+       if (get_panel_type(dev, 0) != TC35876X) { /* FIXME: pipe */
+               p_funcs->reset = mdfld_dsi_panel_reset;
+               p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init;
+       }
+}
diff --git a/drivers/staging/mrst/drv/tpo_cmd.c b/drivers/staging/mrst/drv/tpo_cmd.c
new file mode 100644 (file)
index 0000000..bb1dcd2
--- /dev/null
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+
+#include "displays/tpo_cmd.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "psb_powermgmt.h"
+
+static struct drm_display_mode*
+tpo_cmd_get_config_mode(struct drm_device* dev)
+{
+       struct drm_display_mode *mode;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+       bool use_gct = false;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+       if (!mode)
+               return NULL;
+
+       if (use_gct) {
+               PSB_DEBUG_ENTRY("gct find MIPI panel. \n");
+
+               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+               mode->hsync_start = mode->hdisplay + \
+                               ((ti->hsync_offset_hi << 8) | \
+                               ti->hsync_offset_lo);
+               mode->hsync_end = mode->hsync_start + \
+                               ((ti->hsync_pulse_width_hi << 8) | \
+                               ti->hsync_pulse_width_lo);
+               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+                                                               ti->hblank_lo);
+               mode->vsync_start = \
+                       mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+                                               ti->vsync_offset_lo);
+               mode->vsync_end = \
+                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+                                               ti->vsync_pulse_width_lo);
+               mode->vtotal = mode->vdisplay + \
+                               ((ti->vblank_hi << 8) | ti->vblank_lo);
+               mode->clock = ti->pixel_clock * 10;
+
+               PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay);
+               PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay);
+               PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start);
+               PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end);
+               PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal);
+               PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start);
+               PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end);
+               PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal);
+               PSB_DEBUG_ENTRY("clock is %d\n", mode->clock);
+       } else {
+               mode->hdisplay = 864;
+               mode->vdisplay = 480;
+               mode->hsync_start = 872;
+               mode->hsync_end = 876;
+               mode->htotal = 884;
+               mode->vsync_start = 482;
+               mode->vsync_end = 494;
+               mode->vtotal = 486;
+               mode->clock = 25777;
+       }
+
+       drm_mode_set_name(mode);
+       drm_mode_set_crtcinfo(mode, 0);
+       
+       mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+       return mode;
+}
+
+static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder * encoder,
+                                    struct drm_display_mode * mode,
+                                    struct drm_display_mode * adjusted_mode)
+{
+       struct drm_device* dev = encoder->dev;
+       struct drm_display_mode * fixed_mode = tpo_cmd_get_config_mode(dev);
+
+       PSB_DEBUG_ENTRY("\n");
+
+       if(fixed_mode) {
+               adjusted_mode->hdisplay = fixed_mode->hdisplay;
+               adjusted_mode->hsync_start = fixed_mode->hsync_start;
+               adjusted_mode->hsync_end = fixed_mode->hsync_end;
+               adjusted_mode->htotal = fixed_mode->htotal;
+               adjusted_mode->vdisplay = fixed_mode->vdisplay;
+               adjusted_mode->vsync_start = fixed_mode->vsync_start;
+               adjusted_mode->vsync_end = fixed_mode->vsync_end;
+               adjusted_mode->vtotal = fixed_mode->vtotal;
+               adjusted_mode->clock = fixed_mode->clock;
+               drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+               kfree(fixed_mode);
+       }
+       
+       return true;
+}
+
+static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
+{
+       int ret = 0;
+       struct mdfld_dsi_encoder *dsi_encoder =
+               MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_dbi_output *dbi_output =
+               MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+       struct mdfld_dsi_config *dsi_config =
+               mdfld_dsi_encoder_get_config(dsi_encoder);
+       struct mdfld_dsi_pkg_sender *sender =
+               mdfld_dsi_encoder_get_pkg_sender(dsi_encoder);
+       /*struct drm_device * dev = dbi_output->dev;*/
+       struct drm_device* dev = encoder->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
+       u32 data = 0;
+       
+       PSB_DEBUG_ENTRY("pipe %d : %s, panel on: %s\n",pipe, on ? "On" : "Off", dbi_output->dbi_panel_on ? "True" : "False");
+        
+       if(pipe == 2) {
+               if(on)
+                       dev_priv->dual_mipi = true;
+               else
+                       dev_priv->dual_mipi = false;
+       } else {
+               if (!on)
+                       dev_priv->dual_mipi = false;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+               DRM_ERROR("hw begin failed\n");
+               return;
+       }
+
+       
+       if(on) {
+               if(dbi_output->dbi_panel_on)
+                       goto out_err;
+                                       
+               ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
+               if(ret) {
+                       DRM_ERROR("power on error\n");
+                       goto out_err;
+               }
+    
+               dbi_output->dbi_panel_on = true;
+
+               if(pipe == 2)
+                       dev_priv->dbi_panel_on2 = true;
+               else
+                       dev_priv->dbi_panel_on = true;
+
+               mdfld_enable_te(dev, pipe);
+       } else {
+               if(!dbi_output->dbi_panel_on && !dbi_output->first_boot) 
+                       goto out_err;
+                                       
+               dbi_output->dbi_panel_on = false;
+               dbi_output->first_boot = false;
+                               
+               if (pipe == 2)
+                       dev_priv->dbi_panel_on2 = false;
+               else
+                       dev_priv->dbi_panel_on = false;
+
+               mdfld_disable_te(dev, pipe);
+
+               ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
+               if(ret) {
+                       DRM_ERROR("power on error\n");
+                       goto out_err;
+               }
+       }
+
+       /**
+        * FIXME: this is a WA for TPO panel crash on DPMS on & off around
+        * 83 times. the root cause of this issue is that Booster in
+        * drvIC crashed. Add this WA so that we can resume the driver IC
+        * once we found that booster has a fault
+        */
+       mdfld_dsi_get_power_mode(dsi_config, &data, true);
+       if (on && data && !(data & BIT(7))) {
+               /*soft reset*/
+               mdfld_dsi_send_mcs_short(sender, DCS_SOFT_RESET, 0, 0, true);
+
+               /*init drvIC*/
+               if (dbi_output->p_funcs->drv_ic_init)
+                       dbi_output->p_funcs->drv_ic_init(dsi_config,
+                                                        pipe);
+       }
+
+out_err:
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       
+       if(ret)
+               DRM_ERROR("failed\n");
+       else
+               PSB_DEBUG_ENTRY("successfully\n");
+}
+
+
+static void mdfld_dsi_dbi_mode_set(struct drm_encoder * encoder,
+                                  struct drm_display_mode * mode,
+                                  struct drm_display_mode * adjusted_mode)
+{
+       int ret = 0;
+       struct drm_device * dev = encoder->dev;
+       struct drm_psb_private * dev_priv = (struct drm_psb_private*)dev->dev_private;
+       struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_dbi_output * dsi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+       struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+       struct mdfld_dsi_connector * dsi_connector = dsi_config->connector;
+       struct mdfld_dsi_pkg_sender *sender =
+               mdfld_dsi_encoder_get_pkg_sender(&dsi_output->base);
+       int pipe = dsi_connector->pipe;
+       
+       /*regs*/
+       u32 dspcntr_reg = DSPACNTR;
+       u32 pipeconf_reg = PIPEACONF;
+       
+       /*values*/
+       u32 dspcntr_val = dev_priv->dspcntr;
+       u32 pipeconf_val = dev_priv->pipeconf;
+       u32 h_active_area = mode->hdisplay; 
+       u32 v_active_area = mode->vdisplay; 
+       u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX);
+
+       mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
+               TE_TRIGGER_GPIO_PIN;
+
+       PSB_DEBUG_ENTRY("mipi_val =0x%x\n", mipi_val);
+
+       PSB_DEBUG_ENTRY("type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
+       PSB_DEBUG_ENTRY("h %d v %d\n", mode->hdisplay, mode->vdisplay);
+
+       if(pipe == 2) {
+               dspcntr_reg = DSPCCNTR;
+               pipeconf_reg = PIPECCONF;
+               dspcntr_val = dev_priv->dspcntr2;
+               pipeconf_val = dev_priv->pipeconf2;
+       } else {
+               mipi_val |= 0x2; /*two lanes for port A and C respectively*/
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+               DRM_ERROR("hw begin failed\n");
+               return;
+       }
+       
+       REG_WRITE(dspcntr_reg, dspcntr_val);
+       REG_READ(dspcntr_reg);
+    
+       /*20ms delay before sending exit_sleep_mode*/
+       msleep(20);
+    
+       /*send exit_sleep_mode DCS*/
+       ret = mdfld_dsi_send_mcs_short(sender, DCS_EXIT_SLEEP_MODE, 0, 0, true);
+       if(ret) {
+               DRM_ERROR("sent exit_sleep_mode faild\n");
+               goto out_err;
+       }
+       
+       /*send set_tear_on DCS*/
+       ret = mdfld_dsi_send_mcs_short(sender, DCS_SET_TEAR_ON, 0, 1, true);
+       if (ret) {
+               DRM_ERROR("%s - sent set_tear_on faild\n", __FUNCTION__);
+               goto out_err;
+       }
+       
+       REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
+       REG_READ(pipeconf_reg);
+       
+       /*TODO: this looks ugly, try to move it to CRTC mode setting*/
+       if(pipe == 2) {
+               dev_priv->pipeconf2 |= PIPEACONF_DSR;
+       } else {
+               dev_priv->pipeconf |= PIPEACONF_DSR;
+       }
+       
+       PSB_DEBUG_ENTRY("pipeconf %x\n",  REG_READ(pipeconf_reg));
+       
+       ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, h_active_area - 1, v_active_area - 1);
+       if(ret) {
+               DRM_ERROR("update area failed\n");
+               goto out_err;
+       }
+
+out_err:
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+       if(ret) {
+               DRM_ERROR("mode set failed\n");
+       } else {
+               PSB_DEBUG_ENTRY("mode set done successfully\n");
+       }
+}
+
+static void mdfld_dsi_dbi_prepare(struct drm_encoder * encoder) 
+{
+       struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_dbi_output * dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+       
+       PSB_DEBUG_ENTRY("\n");
+       
+       dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
+       dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
+
+       mdfld_dsi_dbi_set_power(encoder, false);
+       
+}
+
+static void mdfld_dsi_dbi_commit(struct drm_encoder * encoder) 
+{
+       struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_dbi_output * dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+       struct drm_device * dev = dbi_output->dev;
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       
+/*DSI DPU was still on debugging, will remove this option later*/
+#ifdef CONFIG_MDFLD_DSI_DPU            
+       struct psb_drm_dpu_rect rect;
+#endif
+       
+       PSB_DEBUG_ENTRY("\n");
+
+       mdfld_dsi_dbi_set_power(encoder, true);
+       
+       dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+       rect.x = rect.y = 0;
+       rect.width = 864;
+       rect.height = 480;
+#endif 
+       
+       if(dbi_output->channel_num == 1) {
+               dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
+#ifdef CONFIG_MDFLD_DSI_DPU
+               /*if dpu enabled report a fullscreen damage*/
+               mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
+#endif
+       } else {
+               dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
+               
+#ifdef CONFIG_MDFLD_DSI_DPU            
+               mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
+#endif
+       }
+       
+       dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
+}
+
+static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+        struct mdfld_dsi_dbi_output * dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+        struct drm_device * dev = dbi_output->dev;
+       static bool bdispoff = false;
+
+       PSB_DEBUG_ENTRY("%s \n",  (mode == DRM_MODE_DPMS_ON ? "on":"off"));
+
+       if (mode == DRM_MODE_DPMS_ON){
+               /**
+                * FIXME: in case I am wrong!
+                * we don't need to exit dsr here to wake up plane/pipe/pll
+                * if everything goes right, hw_begin will resume them all
+                * during set_power.
+                */
+                if(gbgfxsuspended && bdispoff){
+                        bdispoff = false;
+                        gbdispstatus = true;
+                        gbgfxsuspended = false;
+                        mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_2D_3D);
+                }
+
+               mdfld_dsi_dbi_set_power(encoder, true);
+       } else {
+               /**
+                * I am not sure whether this is the perfect place to 
+                * turn rpm on since we still have a lot of CRTC turnning 
+                * on work to do.
+                */ 
+               bdispoff = true;
+                gbdispstatus = false;
+               mdfld_dsi_dbi_set_power(encoder, false);
+       }
+}
+
+
+/**
+ * Update the DBI MIPI Panel Frame Buffer.
+ */
+static void mdfld_dsi_dbi_update_fb (struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+       struct mdfld_dsi_pkg_sender * sender = 
+               mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+       struct drm_device * dev = dbi_output->dev;
+       struct drm_crtc * crtc = dbi_output->base.base.crtc;
+       struct psb_intel_crtc * psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; 
+
+       u32 dpll_reg = MRST_DPLL_A;
+       u32 dspcntr_reg = DSPACNTR;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dsplinoff_reg = DSPALINOFF;
+       u32 dspsurf_reg = DSPASURF;
+       
+       /*if mode setting on-going, back off*/
+       if((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+               (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
+               !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
+               return;
+               
+       if(pipe == 2) {
+               dspcntr_reg = DSPCCNTR;
+               pipeconf_reg = PIPECCONF;
+               dsplinoff_reg = DSPCLINOFF;
+               dspsurf_reg = DSPCSURF;
+       }
+
+       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+               DRM_ERROR("hw begin failed\n");
+               return;
+       }
+
+       /*check DBI FIFO status*/
+       if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+          !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+          !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
+               goto update_fb_out0;
+       }
+       
+       /*refresh plane changes*/
+       REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
+       REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+       REG_READ(dspsurf_reg);
+
+       mdfld_dsi_write_mem_start(sender);
+       
+       dbi_output->dsr_fb_update_done = true;
+update_fb_out0:
+       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static int tpo_cmd_get_panel_info(struct drm_device * dev,
+                               int pipe,
+                               struct panel_info * pi)
+{
+       if(!dev || !pi)
+               return -EINVAL;
+
+       pi->width_mm = TPO_PANEL_WIDTH;
+       pi->height_mm = TPO_PANEL_HEIGHT;
+
+       return 0;
+}
+
+
+/*TPO DBI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
+       .dpms = mdfld_dsi_dbi_dpms,
+       .mode_fixup = mdfld_dsi_dbi_mode_fixup,
+       .prepare = mdfld_dsi_dbi_prepare,
+       .mode_set = mdfld_dsi_dbi_mode_set,
+       .commit = mdfld_dsi_dbi_commit,
+};
+
+/*TPO DBI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+void tpo_cmd_init(struct drm_device* dev, struct panel_funcs* p_funcs)
+{
+       p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
+       p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs;
+       p_funcs->get_config_mode = &tpo_cmd_get_config_mode;
+       p_funcs->update_fb = mdfld_dsi_dbi_update_fb;
+       p_funcs->get_panel_info = tpo_cmd_get_panel_info;
+       p_funcs->reset = mdfld_dsi_panel_reset;
+       p_funcs->drv_ic_init = mdfld_dsi_brightness_init;
+}
diff --git a/drivers/staging/mrst/drv/tpo_vid.c b/drivers/staging/mrst/drv/tpo_vid.c
new file mode 100644 (file)
index 0000000..f9631c0
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "displays/tpo_vid.h"
+#include "mdfld_dsi_dpi.h"
+
+static struct drm_display_mode*
+tpo_vid_get_config_mode(struct drm_device* dev)
+{
+       struct drm_display_mode *mode;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+       bool use_gct = false;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+       if (!mode)
+               return NULL;
+
+       if (use_gct) {
+               PSB_DEBUG_ENTRY("gct find MIPI panel. \n");
+
+               mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+               mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+               mode->hsync_start = mode->hdisplay + \
+                               ((ti->hsync_offset_hi << 8) | \
+                               ti->hsync_offset_lo);
+               mode->hsync_end = mode->hsync_start + \
+                               ((ti->hsync_pulse_width_hi << 8) | \
+                               ti->hsync_pulse_width_lo);
+               mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+                                                               ti->hblank_lo);
+               mode->vsync_start = \
+                       mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+                                               ti->vsync_offset_lo);
+               mode->vsync_end = \
+                       mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+                                               ti->vsync_pulse_width_lo);
+               mode->vtotal = mode->vdisplay + \
+                               ((ti->vblank_hi << 8) | ti->vblank_lo);
+               mode->clock = ti->pixel_clock * 10;
+
+               PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay);
+               PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay);
+               PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start);
+               PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end);
+               PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal);
+               PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start);
+               PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end);
+               PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal);
+               PSB_DEBUG_ENTRY("clock is %d\n", mode->clock);
+       } else {
+               mode->hdisplay = 864;
+               mode->vdisplay = 480;
+               mode->hsync_start = 873;
+               mode->hsync_end = 876;
+               mode->htotal = 887;
+               mode->vsync_start = 487;
+               mode->vsync_end = 490;
+               mode->vtotal = 499;
+               mode->clock = 33264;
+       }
+
+       drm_mode_set_name(mode);
+       drm_mode_set_crtcinfo(mode, 0);
+       
+       mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+       return mode;
+}
+
+static int tpo_vid_get_panel_info(struct drm_device * dev,
+                               int pipe,
+                               struct panel_info * pi)
+{
+       if(!dev || !pi)
+               return -EINVAL;
+
+       pi->width_mm = TPO_PANEL_WIDTH;
+       pi->height_mm = TPO_PANEL_HEIGHT;
+
+       return 0;
+}
+
+/*TPO DPI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_tpo_dpi_encoder_helper_funcs = {
+       .dpms = mdfld_dsi_dpi_dpms,
+       .mode_fixup = mdfld_dsi_dpi_mode_fixup,
+       .prepare = mdfld_dsi_dpi_prepare,
+       .mode_set = mdfld_dsi_dpi_mode_set,
+       .commit = mdfld_dsi_dpi_commit,
+};
+
+/*TPO DPI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+void tpo_vid_init(struct drm_device* dev, struct panel_funcs* p_funcs)
+{
+       if(!dev || !p_funcs) {
+               DRM_ERROR("Invalid parameters\n");
+               return;
+       }
+       
+       PSB_DEBUG_ENTRY("\n");
+       
+       p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
+       p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
+       p_funcs->get_config_mode = &tpo_vid_get_config_mode;
+       p_funcs->update_fb = NULL;
+       p_funcs->get_panel_info = tpo_vid_get_panel_info;
+}
diff --git a/drivers/staging/mrst/imgv/msvdx_power.c b/drivers/staging/mrst/imgv/msvdx_power.c
new file mode 100644 (file)
index 0000000..f729821
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: binglin.chen@intel.com>
+ *
+ */
+
+#include "msvdx_power.h"
+#include "psb_msvdx.h"
+#include "psb_drv.h"
+#include "psb_powermgmt.h"
+
+#include "services_headers.h"
+#include "sysconfig.h"
+
+static PVRSRV_ERROR DevInitMSVDXPart1(IMG_VOID *pvDeviceNode)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+       PVRSRV_ERROR eError;
+       PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+
+       /* register power operation function */
+       /* FIXME: this should be in part2 init function, but
+        * currently here only OSPM needs IMG device... */
+       eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+       eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
+                                          MSVDXPrePowerState,
+                                          MSVDXPostPowerState,
+                                          MSVDXPreClockSpeedChange,
+                                          MSVDXPostClockSpeedChange,
+                                          (IMG_HANDLE)psDeviceNode,
+                                          PVRSRV_DEV_POWER_STATE_ON,
+                                          eDefaultPowerState);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR, "DevInitMSVDXPart1: failed to "
+                        "register device with power manager"));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DevDeInitMSVDX(IMG_VOID *pvDeviceNode)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+       PVRSRV_ERROR eError;
+
+       /* should deinit all resource */
+
+       eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
+       if (eError != PVRSRV_OK)
+               return eError;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       /* version check */
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       psDeviceNode->sDevId.eDeviceType        = PVRSRV_DEVICE_TYPE_MSVDX;
+       psDeviceNode->sDevId.eDeviceClass       = PVRSRV_DEVICE_CLASS_VIDEO;
+
+       psDeviceNode->pfnInitDevice             = DevInitMSVDXPart1;
+       psDeviceNode->pfnDeInitDevice           = DevDeInitMSVDX;
+
+       psDeviceNode->pfnInitDeviceCompatCheck  = MSVDXDevInitCompatCheck;
+
+       psDeviceNode->pfnDeviceISR = psb_msvdx_interrupt;
+       psDeviceNode->pvISRData = (IMG_VOID *)gpDrmDevice;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPrePowerState(IMG_HANDLE hDevHandle,
+                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState)
+{
+#if 1
+       /* ask for a change not power on*/
+       if ((eNewPowerState != eCurrentPowerState) &&
+           (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+               struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+               struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+               MSVDX_NEW_PMSTATE(gpDrmDevice, msvdx_priv, PSB_PMSTATE_POWERDOWN);
+
+               /* context save */
+               psb_msvdx_save_context(gpDrmDevice);
+
+               /* internally close the device */
+
+               /* ask for power off */
+               if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+                       /* here will deinitialize the driver if needed */
+               } else {
+                       PVR_DPF((PVR_DBG_MESSAGE,
+                                "%s no action for transform from %d to %d",
+                                __func__,
+                                eCurrentPowerState,
+                                eNewPowerState));
+               }
+       }
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPostPowerState(IMG_HANDLE hDevHandle,
+                                PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+#if 1
+       /* if ask for change & current status is not on */
+       if ((eNewPowerState != eCurrentPowerState) &&
+           (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+               /* internally open device */
+               struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+               struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+               MSVDX_NEW_PMSTATE(gpDrmDevice, msvdx_priv, PSB_PMSTATE_POWERUP);
+
+               /* context restore */
+               psb_msvdx_restore_context(gpDrmDevice);
+
+               if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+                       /* here will initialize the driver if needed */
+               } else {
+                       PVR_DPF((PVR_DBG_MESSAGE,
+                                "%s no action for transform from %d to %d",
+                                __func__,
+                                eCurrentPowerState,
+                                eNewPowerState));
+               }
+       }
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+                                     IMG_BOOL bIdleDevice,
+                                     PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+                                      IMG_BOOL bIdleDevice,
+                                      PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+       return PVRSRV_OK;
+}
diff --git a/drivers/staging/mrst/imgv/msvdx_power.h b/drivers/staging/mrst/imgv/msvdx_power.h
new file mode 100644 (file)
index 0000000..479afc7
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: binglin.chen@intel.com>
+ *
+ */
+
+#ifndef MSVDX_POWER_H_
+#define MSVDX_POWER_H_
+
+#include "services_headers.h"
+#include "sysconfig.h"
+
+/* function define */
+PVRSRV_ERROR MSVDXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+PVRSRV_ERROR MSVDXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/* power function define */
+PVRSRV_ERROR MSVDXPrePowerState(IMG_HANDLE     hDevHandle,
+                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+PVRSRV_ERROR MSVDXPostPowerState(IMG_HANDLE    hDevHandle,
+                                PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXPreClockSpeedChange(IMG_HANDLE       hDevHandle,
+                                     IMG_BOOL                  bIdleDevice,
+                                     PVRSRV_DEV_POWER_STATE    eCurrentPowerState);
+PVRSRV_ERROR MSVDXPostClockSpeedChange(IMG_HANDLE      hDevHandle,
+                                      IMG_BOOL                 bIdleDevice,
+                                      PVRSRV_DEV_POWER_STATE   eCurrentPowerState);
+PVRSRV_ERROR MSVDXInitOSPM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#endif /* !MSVDX_POWER_H_ */
diff --git a/drivers/staging/mrst/imgv/pnw_topaz.c b/drivers/staging/mrst/imgv/pnw_topaz.c
new file mode 100644 (file)
index 0000000..db9f61c
--- /dev/null
@@ -0,0 +1,823 @@
+/**
+ * file pnw_topaz.c
+ * TOPAZ I/O operations and IRQ handling
+ *
+ */
+
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+/* include headers */
+/* #define DRM_DEBUG_CODE 2 */
+#include <drm/drmP.h>
+#include <drm/drm_os_linux.h>
+
+#include "psb_drv.h"
+#include "psb_drm.h"
+#include "pnw_topaz.h"
+#include "psb_powermgmt.h"
+#include "pnw_topaz_hw_reg.h"
+
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#define TOPAZ_MAX_COMMAND_IN_QUEUE 0x1000
+//#define SYNC_FOR_EACH_COMMAND
+/* static function define */
+static int pnw_topaz_deliver_command(struct drm_device *dev,
+                                    struct ttm_buffer_object *cmd_buffer,
+                                    unsigned long cmd_offset,
+                                    unsigned long cmd_size,
+                                    void **topaz_cmd, uint32_t sequence,
+                                    int copy_cmd);
+static int pnw_topaz_send(struct drm_device *dev, void *cmd,
+                         unsigned long cmd_size, uint32_t sync_seq);
+static int pnw_topaz_dequeue_send(struct drm_device *dev);
+static int pnw_topaz_save_command(struct drm_device *dev, void *cmd,
+                                 unsigned long cmd_size, uint32_t sequence);
+
+static void pnw_topaz_mtx_kick(struct drm_psb_private *dev_priv,
+                       uint32_t core_id, uint32_t kick_count);
+
+IMG_BOOL pnw_topaz_interrupt(IMG_VOID *pvData)
+{
+       struct drm_device *dev;
+       struct drm_psb_private *dev_priv;
+       uint32_t clr_flag;
+       struct pnw_topaz_private *topaz_priv;
+       uint32_t topaz_stat;
+       uint32_t cur_seq, cmd_id;
+
+       PSB_DEBUG_IRQ("Got an TopazSC interrupt\n");
+
+       if (pvData == IMG_NULL) {
+               DRM_ERROR("ERROR: TOPAZ %s, Invalid params\n", __func__);
+               return IMG_FALSE;
+       }
+
+       dev = (struct drm_device *)pvData;
+
+       if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+               DRM_ERROR("ERROR: interrupt arrived but HW is power off\n");
+               return IMG_FALSE;
+       }
+
+       dev_priv = (struct drm_psb_private *) dev->dev_private;
+       topaz_priv = dev_priv->topaz_private;
+
+       /*TODO : check if topaz is busy*/
+       topaz_priv->topaz_hw_busy = REG_READ(0x20D0) & (0x1 << 11);
+
+       TOPAZ_READ32(TOPAZ_CR_IMG_TOPAZ_INTSTAT, &topaz_stat, 0);
+       clr_flag = pnw_topaz_queryirq(dev);
+
+       pnw_topaz_clearirq(dev, clr_flag);
+
+       TOPAZ_MTX_WB_READ32(topaz_priv->topaz_sync_addr,
+                           0, MTX_WRITEBACK_CMDWORD, &cmd_id);
+       cmd_id = (cmd_id & 0x7f); /* CMD ID */
+       if (cmd_id != MTX_CMDID_NULL)
+               return IMG_TRUE;
+
+       TOPAZ_MTX_WB_READ32(topaz_priv->topaz_sync_addr,
+                           0, MTX_WRITEBACK_VALUE, &cur_seq);
+
+       PSB_DEBUG_IRQ("TOPAZ:Got SYNC IRQ,sync seq:0x%08x (MTX)"
+                     " vs 0x%08x(fence)\n",
+                     cur_seq, dev_priv->sequence[LNC_ENGINE_ENCODE]);
+
+       psb_fence_handler(dev, LNC_ENGINE_ENCODE);
+
+       topaz_priv->topaz_busy = 1;
+       pnw_topaz_dequeue_send(dev);
+
+       if (drm_topaz_pmpolicy != PSB_PMPOLICY_NOPM \
+                       && topaz_priv->topaz_busy == 0) {
+               PSB_DEBUG_IRQ("TOPAZ:Schedule a work to power down Topaz\n");
+               schedule_delayed_work(&dev_priv->scheduler.topaz_suspend_wq, 0);
+       }
+
+       return IMG_TRUE;
+}
+
+//#define PSB_DEBUG_GENERAL DRM_ERROR
+static int pnw_submit_encode_cmdbuf(struct drm_device *dev,
+                                   struct ttm_buffer_object *cmd_buffer,
+                                   unsigned long cmd_offset, unsigned long cmd_size,
+                                   struct ttm_fence_object *fence)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       unsigned long irq_flags;
+       int ret = 0;
+       void *cmd;
+       uint32_t tmp;
+       uint32_t sequence = dev_priv->sequence[LNC_ENGINE_ENCODE];
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       PSB_DEBUG_GENERAL("TOPAZ: command submit\n");
+
+       PSB_DEBUG_GENERAL("TOPAZ: topaz busy = %d\n", topaz_priv->topaz_busy);
+
+       if (dev_priv->last_topaz_ctx != dev_priv->topaz_ctx) {
+               /* todo: save current context into dev_priv->last_topaz_ctx
+                * and reload dev_priv->topaz_ctx context
+                */
+               PSB_DEBUG_GENERAL("TOPAZ: context switch\n");
+               dev_priv->last_topaz_ctx = dev_priv->topaz_ctx;
+       }
+
+       if (topaz_priv->topaz_fw_loaded == 0) {
+               /* #.# load fw to driver */
+               PSB_DEBUG_INIT("TOPAZ: load /lib/firmware/topaz_fwsc.bin\n");
+               ret = pnw_topaz_init_fw(dev);
+               if (ret != 0) {
+                       /* FIXME: find a proper return value */
+                       DRM_ERROR("TOPAX:load /lib/firmware/topaz_fwsc.bin"
+                                 " fails, ensure udevd is configured"
+                                 " correctly!\n");
+                       return -EFAULT;
+               }
+               topaz_priv->topaz_fw_loaded = 1;
+       }
+
+       tmp = atomic_cmpxchg(&dev_priv->topaz_mmu_invaldc, 1, 0);
+       if (tmp == 1)
+               pnw_topaz_mmu_flushcache(dev_priv);
+
+       /* # schedule watchdog */
+       /* psb_schedule_watchdog(dev_priv); */
+
+       /* # spin lock irq save [msvdx_lock] */
+       spin_lock_irqsave(&topaz_priv->topaz_lock, irq_flags);
+
+       /* # if topaz need to reset, reset it */
+       if (topaz_priv->topaz_needs_reset) {
+               /* #.# reset it */
+               spin_unlock_irqrestore(&topaz_priv->topaz_lock, irq_flags);
+               PSB_DEBUG_GENERAL("TOPAZ: needs reset.\n");
+
+               if (pnw_topaz_reset(dev_priv)) {
+                       ret = -EBUSY;
+                       DRM_ERROR("TOPAZ: reset failed.\n");
+                       return ret;
+               }
+
+               PSB_DEBUG_GENERAL("TOPAZ: reset ok.\n");
+
+               /* #.# upload firmware */
+               if (pnw_topaz_setup_fw(dev, topaz_priv->topaz_cur_codec)) {
+                       DRM_ERROR("TOPAZ: upload FW to HW failed\n");
+                       return -EBUSY;
+               }
+
+               spin_lock_irqsave(&topaz_priv->topaz_lock, irq_flags);
+       }
+
+       if (!topaz_priv->topaz_busy) {
+               /* # direct map topaz command if topaz is free */
+               PSB_DEBUG_GENERAL("TOPAZ:direct send command,sequence %08x\n",
+                                 sequence);
+
+               topaz_priv->topaz_busy = 1;
+               spin_unlock_irqrestore(&topaz_priv->topaz_lock, irq_flags);
+
+               ret = pnw_topaz_deliver_command(dev, cmd_buffer, cmd_offset,
+                                               cmd_size, NULL, sequence, 0);
+
+               if (ret) {
+                       DRM_ERROR("TOPAZ: failed to extract cmd...\n");
+                       return ret;
+               }
+       } else {
+               PSB_DEBUG_GENERAL("TOPAZ: queue command,sequence %08x \n",
+                                 sequence);
+               cmd = NULL;
+
+               spin_unlock_irqrestore(&topaz_priv->topaz_lock, irq_flags);
+
+               ret = pnw_topaz_deliver_command(dev, cmd_buffer, cmd_offset,
+                                               cmd_size, &cmd, sequence, 1);
+               if (cmd == NULL || ret) {
+                       DRM_ERROR("TOPAZ: map command for save fialed\n");
+                       return ret;
+               }
+
+               ret = pnw_topaz_save_command(dev, cmd, cmd_size, sequence);
+               if (ret)
+                       DRM_ERROR("TOPAZ: save command failed\n");
+       }
+
+       return ret;
+}
+
+static int pnw_topaz_save_command(struct drm_device *dev, void *cmd,
+                                 unsigned long cmd_size, uint32_t sequence)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct pnw_topaz_cmd_queue *topaz_cmd;
+       unsigned long irq_flags;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       PSB_DEBUG_GENERAL("TOPAZ: queue command,sequence: %08x..\n",
+                         sequence);
+
+       topaz_cmd = kzalloc(sizeof(struct pnw_topaz_cmd_queue),
+                           GFP_KERNEL);
+       if (topaz_cmd == NULL) {
+               mutex_unlock(&topaz_priv->topaz_mutex);
+               DRM_ERROR("TOPAZ: out of memory....\n");
+               return -ENOMEM;
+       }
+
+       topaz_cmd->cmd = cmd;
+       topaz_cmd->cmd_size = cmd_size;
+       topaz_cmd->sequence = sequence;
+
+       spin_lock_irqsave(&topaz_priv->topaz_lock, irq_flags);
+       list_add_tail(&topaz_cmd->head, &topaz_priv->topaz_queue);
+       if (!topaz_priv->topaz_busy) {
+               /* topaz_priv->topaz_busy = 1; */
+               PSB_DEBUG_GENERAL("TOPAZ: need immediate dequeue...\n");
+               pnw_topaz_dequeue_send(dev);
+               PSB_DEBUG_GENERAL("TOPAZ: after dequeue command\n");
+       }
+
+       spin_unlock_irqrestore(&topaz_priv->topaz_lock, irq_flags);
+
+       return 0;
+}
+
+
+int pnw_cmdbuf_video(struct drm_file *priv,
+                    struct list_head *validate_list,
+                    uint32_t fence_type,
+                    struct drm_psb_cmdbuf_arg *arg,
+                    struct ttm_buffer_object *cmd_buffer,
+                    struct psb_ttm_fence_rep *fence_arg)
+{
+       struct drm_device *dev = priv->minor->dev;
+       struct ttm_fence_object *fence = NULL;
+       int ret;
+
+       PSB_DEBUG_GENERAL("TOPAZ : enter %s cmdsize: %d\n", __func__,
+                         arg->cmdbuf_size);
+
+       ret = pnw_submit_encode_cmdbuf(dev, cmd_buffer, arg->cmdbuf_offset,
+                                      arg->cmdbuf_size, fence);
+       if (ret)
+               return ret;
+
+       /* workaround for interrupt issue */
+       psb_fence_or_sync(priv, LNC_ENGINE_ENCODE, fence_type, arg->fence_flags,
+                         validate_list, fence_arg, &fence);
+
+       if (fence)
+               ttm_fence_object_unref(&fence);
+
+       spin_lock(&cmd_buffer->bdev->fence_lock);
+       if (cmd_buffer->sync_obj != NULL)
+               ttm_fence_sync_obj_unref(&cmd_buffer->sync_obj);
+       spin_unlock(&cmd_buffer->bdev->fence_lock);
+
+       PSB_DEBUG_GENERAL("TOPAZ exit %s\n", __func__);
+       return 0;
+}
+
+int pnw_wait_on_sync(struct drm_psb_private *dev_priv,
+                    uint32_t sync_seq,
+                    uint32_t *sync_p)
+{
+       int count = 10000;
+       if (sync_p == NULL) {
+               DRM_ERROR("TOPAZ: pnw_wait_on_sync invalid memory address\n ");
+               return -1;
+       }
+
+       while (count && (sync_seq != *sync_p)) {
+               PSB_UDELAY(100);
+               --count;
+       }
+       if ((count == 0) && (sync_seq != *sync_p)) {
+               DRM_ERROR("TOPAZ: wait sycn timeout (0x%08x),actual 0x%08x\n",
+                         sync_seq, *sync_p);
+               return -EBUSY;
+       }
+       PSB_DEBUG_GENERAL("TOPAZ: SYNC done, seq=0x%08x\n", *sync_p);
+       return 0;
+}
+
+static int pnw_topaz_deliver_command(struct drm_device *dev,
+                             struct ttm_buffer_object *cmd_buffer,
+                             unsigned long cmd_offset, unsigned long cmd_size,
+                             void **topaz_cmd, uint32_t sequence,
+                             int copy_cmd)
+{
+       unsigned long cmd_page_offset = cmd_offset & ~PAGE_MASK;
+       struct ttm_bo_kmap_obj cmd_kmap;
+       bool is_iomem;
+       int ret;
+       unsigned char *cmd_start, *tmp;
+
+       ret = ttm_bo_kmap(cmd_buffer, cmd_offset >> PAGE_SHIFT, 2,
+                         &cmd_kmap);
+       if (ret) {
+               DRM_ERROR("TOPAZ: drm_bo_kmap failed: %d\n", ret);
+               return ret;
+       }
+       cmd_start = (unsigned char *) ttm_kmap_obj_virtual(&cmd_kmap,
+                       &is_iomem) + cmd_page_offset;
+
+       if (copy_cmd) {
+               PSB_DEBUG_GENERAL("TOPAZ: queue commands\n");
+               tmp = kzalloc(cmd_size, GFP_KERNEL);
+               if (tmp == NULL) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               memcpy(tmp, cmd_start, cmd_size);
+               *topaz_cmd = tmp;
+       } else {
+               PSB_DEBUG_GENERAL("TOPAZ: directly send the command\n");
+               ret = pnw_topaz_send(dev, cmd_start, cmd_size, sequence);
+               if (ret) {
+                       DRM_ERROR("TOPAZ: commit commands failed.\n");
+                       ret = -EINVAL;
+               }
+       }
+
+out:
+       PSB_DEBUG_GENERAL("TOPAZ:cmd_size(%ld), sequence(%d)"
+                         " copy_cmd(%d)\n",
+                         cmd_size, sequence, copy_cmd);
+
+       ttm_bo_kunmap(&cmd_kmap);
+
+       return ret;
+}
+
+
+int pnw_topaz_kick_null_cmd(struct drm_psb_private *dev_priv,
+                           uint32_t core_id,
+                           uint32_t wb_offset,
+                           uint32_t sync_seq,
+                           uint8_t irq_enable)
+{
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       uint32_t cur_free_space;
+       struct topaz_cmd_header cur_cmd_header;
+       int ret;
+
+       POLL_TOPAZ_FREE_FIFO_SPACE(4, 100, 10000, &cur_free_space);
+       if (ret) {
+               DRM_ERROR("TOPAZ: error -- ret(%d)\n", ret);
+               return ret;
+       }
+
+       cur_cmd_header.core = core_id;
+       cur_cmd_header.seq = sync_seq,
+                      cur_cmd_header.enable_interrupt = ((irq_enable == 0) ? 0 : 1);
+       cur_cmd_header.id = MTX_CMDID_NULL;
+
+       topaz_priv->topaz_cmd_count %= MAX_TOPAZ_CMD_COUNT;
+       PSB_DEBUG_GENERAL("TOPAZ: free FIFO space %d\n",
+                         cur_free_space);
+       PSB_DEBUG_GENERAL("TOPAZ: write 4 words to FIFO:"
+                         "0x%08x,0x%08x,0x%08x,0x%08x\n",
+                         cur_cmd_header.val,
+                         0,
+                         wb_offset,
+                         cur_cmd_header.seq);
+
+       TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+                               cur_cmd_header.val);
+       TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+                               0);
+       TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+                               wb_offset);
+       TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+                               sync_seq);
+
+       PSB_DEBUG_GENERAL("TOPAZ: Write back value for NULL CMD is %d\n",
+                         sync_seq);
+
+       pnw_topaz_mtx_kick(dev_priv, 0, 1);
+
+       return 0;
+}
+
+static int
+pnw_topaz_send(struct drm_device *dev, void *cmd,
+              unsigned long cmd_size, uint32_t sync_seq)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int ret = 0;
+       unsigned char *command = (unsigned char *) cmd;
+       struct topaz_cmd_header *cur_cmd_header;
+       uint32_t cur_cmd_size = 4, cur_cmd_id, cur_free_space = 0;
+       uint32_t codec;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       uint32_t reg_off, reg_val, reg_cnt;
+       uint32_t *p_command;
+
+       PSB_DEBUG_GENERAL("TOPAZ: send the command in the buffer one by one\n");
+
+       while (cmd_size > 0) {
+               cur_cmd_header = (struct topaz_cmd_header *) command;
+               cur_cmd_id = cur_cmd_header->id;
+               PSB_DEBUG_GENERAL("TOPAZ: %s: \n", cmd_to_string(cur_cmd_id));
+
+               switch (cur_cmd_id) {
+               case MTX_CMDID_SW_NEW_CODEC:
+                       codec = *((uint32_t *) cmd + 1);
+                       topaz_priv->frame_h = (uint16_t)
+                                             ((*((uint32_t *) cmd + 2)) & 0xffff) ;
+                       topaz_priv->frame_w = (uint16_t)
+                                             (((*((uint32_t *) cmd + 2))
+                                               & 0xffff0000)  >> 16) ;
+
+                       PSB_DEBUG_GENERAL("TOPAZ: setup new codec %s (%d),"
+                                         " width %d, height %d\n",
+                                         codec_to_string(codec), codec,
+                                         topaz_priv->frame_w,
+                                         topaz_priv->frame_h);
+                       if (pnw_topaz_setup_fw(dev, codec)) {
+                               DRM_ERROR("TOPAZ: upload FW to HW failed\n");
+                               return -EBUSY;
+                       }
+                       topaz_priv->topaz_cur_codec = codec;
+                       cur_cmd_size = 3;
+                       break;
+
+               case MTX_CMDID_SW_ENTER_LOWPOWER:
+                       PSB_DEBUG_GENERAL("TOPAZ: enter lowpower.... \n");
+                       PSB_DEBUG_GENERAL("XXX: implement it\n");
+                       cur_cmd_size = 1;
+                       break;
+
+               case MTX_CMDID_SW_LEAVE_LOWPOWER:
+                       PSB_DEBUG_GENERAL("TOPAZ: leave lowpower... \n");
+                       PSB_DEBUG_GENERAL("XXX: implement it\n");
+                       cur_cmd_size = 1;
+                       break;
+
+               case MTX_CMDID_SW_WRITEREG:
+                       p_command = (uint32_t *)(command);
+                       p_command++;
+                       cur_cmd_size = *p_command;
+                       p_command++;
+                       PSB_DEBUG_GENERAL("TOPAZ: Start to write"
+                                         " %d Registers\n", cur_cmd_size);
+                       if (cur_cmd_size > (cmd_size / 4)) {
+                               DRM_ERROR("TOPAZ: Wrong number of write "
+                                         "operations.Exceed command buffer."
+                                         "(%d)\n", (int)(cmd_size / 4));
+                               goto out;
+                       }
+
+                       for (reg_cnt = 0; reg_cnt < cur_cmd_size; reg_cnt++) {
+                               reg_off = *p_command;
+                               p_command++;
+                               reg_val = *p_command;
+                               p_command++;
+                               if (reg_off > TOPAZSC_REG_OFF_MAX)
+                                       DRM_ERROR("TOPAZ: Ignore write (0x%08x)"
+                                                 " to register 0x%08x\n",
+                                                 reg_val, reg_off);
+                               else
+                                       MM_WRITE32(0, reg_off, reg_val);
+                       }
+                       /* Reg_off and reg_val are stored in a pair of words*/
+                       cur_cmd_size *= 2;
+                       /* Header size, 2 words */
+                       cur_cmd_size += 2;
+                       break;
+               case MTX_CMDID_PAD:
+                       /*Ignore this command, which is used to skip
+                        * some commands in user space*/
+                       cur_cmd_size = 4;
+                       break;
+                       /* ordinary commmand */
+               case MTX_CMDID_START_PIC:
+               case MTX_CMDID_DO_HEADER:
+               case MTX_CMDID_ENCODE_SLICE:
+               case MTX_CMDID_END_PIC:
+               case MTX_CMDID_SETQUANT:
+               case MTX_CMDID_RESET_ENCODE:
+               case MTX_CMDID_ISSUEBUFF:
+               case MTX_CMDID_SETUP:
+                       cur_cmd_header->seq = topaz_priv->topaz_cmd_count++;
+                       cur_cmd_header->enable_interrupt = 0;
+                       cur_cmd_size = 4;
+                       if (cur_free_space < cur_cmd_size) {
+                               POLL_TOPAZ_FREE_FIFO_SPACE(4, 100, 10000,
+                                                          &cur_free_space);
+                               if (ret) {
+                                       DRM_ERROR("TOPAZ: error -- ret(%d)\n",
+                                                 ret);
+                                       goto out;
+                               }
+                       }
+
+                       PSB_DEBUG_GENERAL("TOPAZ: free FIFO space %d\n",
+                                         cur_free_space);
+                       PSB_DEBUG_GENERAL("TOPAZ: write 4 words to FIFO:"
+                                         "0x%08x,0x%08x,0x%08x,0x%08x\n",
+                                         cur_cmd_header->val,
+                                         *((uint32_t *)(command) + 1),
+                                         TOPAZ_MTX_WB_OFFSET(
+                                                 topaz_priv->topaz_wb_offset,
+                                                 cur_cmd_header->core),
+                                         cur_cmd_header->seq);
+
+                       TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+                                               cur_cmd_header->val);
+                       TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+                                               *((uint32_t *)(command) + 1));
+                       TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+                                               TOPAZ_MTX_WB_OFFSET(
+                                                       topaz_priv->topaz_wb_offset,
+                                                       cur_cmd_header->core));
+                       TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+                                               cur_cmd_header->seq);
+
+                       cur_free_space -= 4;
+                       topaz_priv->aui32LastSync[0][cur_cmd_header->core]
+                       = cur_cmd_header->seq;
+                       topaz_priv->topaz_cmd_count %= MAX_TOPAZ_CMD_COUNT;
+                       pnw_topaz_mtx_kick(dev_priv, 0, 1);
+#ifdef SYNC_FOR_EACH_COMMAND
+                       pnw_wait_on_sync(dev_priv, cur_cmd_header->seq,
+                                        topaz_priv->topaz_mtx_wb +
+                                        cur_cmd_header->core *
+                                        MTX_WRITEBACK_DATASIZE_ROUND + 1);
+#endif
+                       break;
+               default:
+                       DRM_ERROR("TOPAZ: unsupported command id: %x\n",
+                                 cur_cmd_id);
+                       goto out;
+               }
+
+               /*cur_cmd_size indicate the number of words of current command*/
+               command += cur_cmd_size * 4;
+               cmd_size -= cur_cmd_size * 4;
+       }
+#if PNW_TOPAZ_NO_IRQ
+       PSB_DEBUG_GENERAL("reset NULL writeback to 0xffffffff,"
+                         "topaz_priv->topaz_sync_addr=0x%p\n",
+                         topaz_priv->topaz_sync_addr);
+
+       *((uint32_t *)topaz_priv->topaz_sync_addr + MTX_WRITEBACK_VALUE) = ~0;
+       pnw_topaz_kick_null_cmd(dev_priv, 0,
+                               topaz_priv->topaz_sync_offset, sync_seq, 0);
+
+       if (0 != pnw_wait_on_sync(dev_priv, sync_seq,
+                                 topaz_priv->topaz_sync_addr + MTX_WRITEBACK_VALUE)) {
+               DRM_ERROR("TOPAZSC: Polling the writeback of last command"
+                         " failed!\n");
+               topaz_read_core_reg(dev_priv,  0, 0x5, &reg_val);
+               DRM_ERROR("TOPAZSC: PC pointer of core 0 is %x\n", reg_val);
+               topaz_read_core_reg(dev_priv, 1, 0x5, &reg_val);
+               DRM_ERROR("TOPAZSC: PC pointer of core 1 is %x\n", reg_val);
+               TOPAZ_MULTICORE_READ32(TOPAZSC_CR_MULTICORE_CMD_FIFO_1,
+                                      &reg_val);
+               reg_val &= MASK_TOPAZSC_CR_CMD_FIFO_SPACE;
+               DRM_ERROR("TOPAZSC: Free words in command FIFO %d\n", reg_val);
+               DRM_ERROR("TOPAZSC: Last writeback of core 0 %d\n",
+                         *(topaz_priv->topaz_mtx_wb +  1));
+               DRM_ERROR("TOPAZSC: Last writeback of core 1 %d\n",
+                         *(topaz_priv->topaz_mtx_wb +
+                           MTX_WRITEBACK_DATASIZE_ROUND + 1));
+       }
+
+       PSB_DEBUG_GENERAL("Kicked command with sequence 0x%08x,"
+                         " and polling it, got 0x%08x\n",
+                         sync_seq,
+                         *(topaz_priv->topaz_sync_addr + MTX_WRITEBACK_VALUE));
+       PSB_DEBUG_GENERAL("Can handle unfence here, but let fence"
+                         " polling do it\n");
+       topaz_priv->topaz_busy = 0;
+#else
+       PSB_DEBUG_GENERAL("Kick command with sequence %x\n", sync_seq);
+       pnw_topaz_kick_null_cmd(dev_priv, 0,
+                               topaz_priv->topaz_sync_offset,
+                               sync_seq, 1);
+#endif
+out:
+       return ret;
+}
+
+static int pnw_topaz_dequeue_send(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct pnw_topaz_cmd_queue *topaz_cmd = NULL;
+       int ret;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       PSB_DEBUG_GENERAL("TOPAZ: dequeue command and send it to topaz\n");
+
+       if (list_empty(&topaz_priv->topaz_queue)) {
+               topaz_priv->topaz_busy = 0;
+               return 0;
+       }
+
+       topaz_priv->topaz_busy = 1;
+       topaz_cmd = list_first_entry(&topaz_priv->topaz_queue,
+                                    struct pnw_topaz_cmd_queue, head);
+
+       PSB_DEBUG_GENERAL("TOPAZ: queue has id %08x\n", topaz_cmd->sequence);
+       ret = pnw_topaz_send(dev, topaz_cmd->cmd, topaz_cmd->cmd_size,
+                            topaz_cmd->sequence);
+       if (ret) {
+               DRM_ERROR("TOPAZ: pnw_topaz_send failed.\n");
+               ret = -EINVAL;
+       }
+
+       list_del(&topaz_cmd->head);
+       kfree(topaz_cmd->cmd);
+       kfree(topaz_cmd);
+
+       return ret;
+}
+
+static void pnw_topaz_mtx_kick(struct drm_psb_private *dev_priv, uint32_t core_id, uint32_t kick_count)
+{
+       PSB_DEBUG_GENERAL("TOPAZ: kick core(%d) mtx count(%d).\n",
+                         core_id, kick_count);
+       topaz_set_mtx_target(dev_priv, core_id, 0);
+       MTX_WRITE32(MTX_CR_MTX_KICK, kick_count, core_id);
+       return;
+}
+
+int pnw_check_topaz_idle(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       if (dev_priv->topaz_ctx == NULL)
+               return 0;
+
+       if (topaz_priv->topaz_busy)
+               return -EBUSY;
+
+       if (topaz_priv->topaz_hw_busy) {
+               PSB_DEBUG_PM("TOPAZ: %s, HW is busy\n", __func__);
+               return -EBUSY;
+       }
+
+       return 0; /* we think it is idle */
+}
+
+
+int pnw_video_get_core_num(struct drm_device *dev, uint64_t user_pointer)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       int ret;
+
+       ret = copy_to_user((void __user *)((unsigned long)user_pointer),
+                          &topaz_priv->topaz_num_cores,
+                          sizeof(topaz_priv->topaz_num_cores));
+
+       if (ret)
+               return -EFAULT;
+
+       return 0;
+
+}
+
+int pnw_video_frameskip(struct drm_device *dev, uint64_t user_pointer)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       int ret;
+
+       ret = copy_to_user((void __user *)((unsigned long)user_pointer),
+                          &topaz_priv->frame_skip, sizeof(topaz_priv->frame_skip));
+
+       if (ret)
+               return -EFAULT;
+
+       return 0;
+}
+
+static void pnw_topaz_flush_cmd_queue(struct pnw_topaz_private *topaz_priv)
+{
+       struct pnw_topaz_cmd_queue *entry, *next;
+
+       /* remind to reset topaz */
+       topaz_priv->topaz_needs_reset = 1;
+
+       if (list_empty(&topaz_priv->topaz_queue)) {
+               topaz_priv->topaz_busy = 0;
+               return;
+       }
+
+       /* flush all command in queue */
+       list_for_each_entry_safe(entry, next,
+                                &topaz_priv->topaz_queue,
+                                head) {
+               list_del(&entry->head);
+               kfree(entry->cmd);
+               kfree(entry);
+       }
+
+       return;
+}
+
+void pnw_topaz_handle_timeout(struct ttm_fence_device *fdev)
+{
+       struct drm_psb_private *dev_priv =
+               container_of(fdev, struct drm_psb_private, fdev);
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       pnw_topaz_flush_cmd_queue(topaz_priv);
+}
+
+
+void pnw_map_topaz_reg(struct drm_device *dev)
+{
+       unsigned long resource_start;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+
+       resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
+
+       if (!dev_priv->topaz_disabled) {
+               dev_priv->topaz_reg = ioremap(
+                                             resource_start + PNW_TOPAZ_OFFSET,
+                                             PNW_TOPAZ_SIZE);
+               if (!dev_priv->topaz_reg)
+                       DRM_ERROR("failed to map TOPAZ register address\n");
+       }
+
+       return;
+}
+
+void pnw_unmap_topaz_reg(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+
+       if (dev_priv->topaz_reg) {
+               iounmap(dev_priv->topaz_reg);
+               dev_priv->topaz_reg = NULL;
+       }
+
+       return;
+}
+
+void pnw_topaz_enableirq(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       /* uint32_t ier = dev_priv->vdc_irq_mask | _PNW_IRQ_TOPAZ_FLAG; */
+
+       PSB_DEBUG_IRQ("TOPAZ: enable IRQ\n");
+
+       /* Only enable the master core IRQ*/
+       TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTENAB,
+                     F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MAS_INTEN) |
+                     /* F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTEN_MVEA) | */
+                     F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTEN_MMU_FAULT) |
+                     F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTEN_MTX) |
+                     F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTEN_MTX_HALT),
+                     0);
+
+       /* write in sysirq.c */
+       /* PSB_WVDC32(ier, PSB_INT_ENABLE_R); /\* essential *\/ */
+}
+
+void pnw_topaz_disableirq(struct drm_device *dev)
+{
+
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       /*uint32_t ier = dev_priv->vdc_irq_mask & (~_PNW_IRQ_TOPAZ_FLAG); */
+
+       PSB_DEBUG_INIT("TOPAZ: disable IRQ\n");
+
+       TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTENAB, 0, 0);
+
+       /* write in sysirq.c */
+       /* PSB_WVDC32(ier, PSB_INT_ENABLE_R); /\* essential *\/ */
+}
+
diff --git a/drivers/staging/mrst/imgv/pnw_topaz.h b/drivers/staging/mrst/imgv/pnw_topaz.h
new file mode 100644 (file)
index 0000000..c8e38d8
--- /dev/null
@@ -0,0 +1,158 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PNW_TOPAZ_H_
+#define _PNW_TOPAZ_H_
+
+#include "psb_drv.h"
+#include "img_types.h"
+
+#define PNW_TOPAZ_NO_IRQ 0
+#define TOPAZ_MTX_REG_SIZE (34 * 4 + 183 * 4)
+#define MAX_TOPAZ_CORES 2
+
+/*Must be equal to IMG_CODEC_NUM*/
+#define PNW_TOPAZ_CODEC_NUM_MAX (11)
+//#define TOPAZ_PDUMP
+
+extern int drm_topaz_pmpolicy;
+
+/* XXX: it's a copy of msvdx cmd queue. should have some change? */
+struct pnw_topaz_cmd_queue {
+       struct list_head head;
+       void *cmd;
+       unsigned long cmd_size;
+       uint32_t sequence;
+};
+
+/* define structure */
+/* firmware file's info head */
+struct topazsc_fwinfo {
+       unsigned int ver: 16;
+       unsigned int codec: 16;
+
+       unsigned int text_size;
+       unsigned int data_size;
+       unsigned int data_location;
+};
+
+/* firmware data array define  */
+struct pnw_topaz_codec_fw {
+       uint32_t ver;
+       uint32_t codec;
+
+       uint32_t text_size;
+       uint32_t data_size;
+       uint32_t data_location;
+
+       struct ttm_buffer_object *text;
+       struct ttm_buffer_object *data;
+};
+
+struct pnw_topaz_private {
+       unsigned int pmstate;
+       struct sysfs_dirent *sysfs_pmstate;
+       int frame_skip;
+
+       void *topaz_mtx_reg_state[MAX_TOPAZ_CORES] ;
+       struct ttm_buffer_object *topaz_mtx_data_mem[MAX_TOPAZ_CORES];
+       uint32_t topaz_cur_codec;
+       uint32_t cur_mtx_data_size[MAX_TOPAZ_CORES];
+       int topaz_needs_reset;
+
+       /*
+        *topaz command queue
+        */
+       spinlock_t topaz_lock;
+       struct mutex topaz_mutex;
+       struct list_head topaz_queue;
+       int topaz_busy;         /* 0 means topaz is free */
+       int topaz_fw_loaded;
+
+       uint32_t stored_initial_qp;
+       uint32_t topaz_dash_access_ctrl;
+
+       struct ttm_buffer_object *topaz_bo; /* 4K->2K/2K for writeback/sync */
+       struct ttm_bo_kmap_obj topaz_bo_kmap;
+       uint32_t *topaz_mtx_wb;
+       uint32_t topaz_wb_offset;
+       uint32_t *topaz_sync_addr;
+       uint32_t topaz_sync_offset;
+       uint32_t topaz_cmd_count;
+       uint32_t topaz_mtx_saved;
+
+
+       /* firmware */
+       struct pnw_topaz_codec_fw topaz_fw[PNW_TOPAZ_CODEC_NUM_MAX * 2];
+
+       uint32_t topaz_hw_busy;
+
+       uint32_t topaz_num_cores;
+       uint32_t aui32LastSync[2][MAX_TOPAZ_CORES + 1];  //!< Last sync value sent to each core
+
+       /*Before load firmware, need to set up jitter according to resolution*/
+       /*The data of MTX_CMDID_SW_NEW_CODEC command contains width and length.*/
+       uint16_t frame_w;
+       uint16_t frame_h;
+};
+
+/* external function declare */
+/*ISR of TopazSC*/
+extern IMG_BOOL pnw_topaz_interrupt(IMG_VOID *pvData);
+
+/*topaz commad handling function*/
+extern int pnw_cmdbuf_video(struct drm_file *priv,
+                           struct list_head *validate_list,
+                           uint32_t fence_type,
+                           struct drm_psb_cmdbuf_arg *arg,
+                           struct ttm_buffer_object *cmd_buffer,
+                           struct psb_ttm_fence_rep *fence_arg);
+extern int pnw_wait_topaz_idle(struct drm_device *dev);
+extern int pnw_check_topaz_idle(struct drm_device *dev);
+extern void pnw_unmap_topaz_reg(struct drm_device *dev);
+extern void pnw_map_topaz_reg(struct drm_device *dev);
+extern int pnw_topaz_restore_mtx_state(struct drm_device *dev);
+extern void pnw_topaz_enableirq(struct drm_device *dev);
+extern void pnw_topaz_disableirq(struct drm_device *dev);
+
+extern int pnw_topaz_init(struct drm_device *dev);
+extern int pnw_topaz_uninit(struct drm_device *dev);
+extern void pnw_topaz_handle_timeout(struct ttm_fence_device *fdev);
+
+extern int pnw_topaz_save_mtx_state(struct drm_device *dev);
+extern void pnw_reset_fw_status(struct drm_device *dev);
+
+extern void topaz_write_core_reg(struct drm_psb_private *dev_priv,
+                                uint32_t core,
+                                uint32_t reg,
+                                const uint32_t val);
+extern void topaz_read_core_reg(struct drm_psb_private *dev_priv,
+                               uint32_t core,
+                               uint32_t reg,
+                               uint32_t *ret_val);
+#define PNW_TOPAZ_NEW_PMSTATE(drm_dev, topaz_priv, new_state)          \
+do { \
+       topaz_priv->pmstate = new_state;                                \
+       sysfs_notify_dirent(topaz_priv->sysfs_pmstate);                 \
+       PSB_DEBUG_PM("TOPAZ: %s\n",                                     \
+               (new_state == PSB_PMSTATE_POWERUP) ? "powerup": "powerdown"); \
+} while (0)
+
+#endif /* _PNW_TOPAZ_H_ */
diff --git a/drivers/staging/mrst/imgv/pnw_topaz_hw_reg.h b/drivers/staging/mrst/imgv/pnw_topaz_hw_reg.h
new file mode 100644 (file)
index 0000000..549f5f3
--- /dev/null
@@ -0,0 +1,1359 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PNW_TOPAZ_HW_REG_H_
+#define _PNW_TOPAZ_HW_REG_H_
+
+#include "psb_drv.h"
+#include "img_types.h"
+#include "pnw_topaz.h"
+
+/*
+ * MACROS to insert values into fields within a word. The basename of the
+ * field must have MASK_BASENAME and SHIFT_BASENAME constants.
+ */
+#define MM_WRITE32(base, offset, value)  \
+do {                                  \
+       *((unsigned long *)((unsigned char *)(dev_priv->topaz_reg)      \
+                               + base + offset)) = value;              \
+} while (0)
+
+#define MM_READ32(base, offset, pointer) \
+do {                                   \
+       *(pointer) = *((unsigned long *)((unsigned char *)(dev_priv->topaz_reg)\
+                                               + base + offset));      \
+} while (0)
+
+#define F_MASK(basename)  (MASK_##basename)
+#define F_SHIFT(basename) (SHIFT_##basename)
+
+#define F_ENCODE(val, basename)  \
+       (((val) << (F_SHIFT(basename))) & (F_MASK(basename)))
+
+
+#define F_EXTRACT(val,basename) (((val)&(F_MASK(basename)))>>(F_SHIFT(basename)))
+
+/*! The number of TOPAZ cores present in the system */
+#define TOPAZSC_NUM_CORES 2
+
+#define TOPAZSC_REG_OFF_MAX (TOPAZSC_NUM_CORES * 0x10000 + 0x10000)
+#define REG_BASE_MTX                        0x04800000
+#define REG_BASE_HOST                       0x00000000
+
+#define MTX_CORE_CODE_MEM       (0x10)
+#define MTX_CORE_DATA_MEM       (0x18)
+
+/* Multicore Regs */
+#define REG_OFFSET_TOPAZ_MULTICORE     0x00000000
+#define REG_OFFSET_TOPAZ_DMAC          0x00001000
+
+#define REG_SIZE_TOPAZ_MULTICORE       0x00001000
+#define REG_SIZE_TOPAZ_DMAC            0x00001000
+
+/* Topaz core registers - Host view */
+#define REG_OFFSET_TOPAZ_CORE_HOST     0x00010000
+#define REG_SIZE_TOPAZ_CORE_HOST       0x00010000
+
+#define REG_OFFSET_TOPAZ_MTX_HOST      0x00000000
+#define REG_OFFSET_TOPAZ_TOPAZ_HOST    0x00002000
+#define REG_OFFSET_TOPAZ_MVEA_HOST     0x00003000
+#define REG_OFFSET_TOPAZ_MVEACMD_HOST  0x00004000
+#define REG_OFFSET_TOPAZ_VLC_HOST      0x00005000
+#define REG_OFFSET_TOPAZ_DEBLOCKER_HOST        0x00006000
+#define REG_OFFSET_TOPAZ_COMMS_HOST    0x00007000
+#define REG_OFFSET_TOPAZ_ESB_HOST      0x00008000
+
+#define REG_SIZE_TOPAZ_MTX_HOST        0x00002000
+#define REG_SIZE_TOPAZ_TOPAZ_HOST      0x00001000
+#define REG_SIZE_TOPAZ_MVEA_HOST       0x00001000
+#define REG_SIZE_TOPAZ_MVEACMD_HOST    0x00001000
+#define REG_SIZE_TOPAZ_VLC_HOST        0x00001000
+#define REG_SIZE_TOPAZ_DEBLOCKER_HOST  0x00001000
+#define REG_SIZE_TOPAZ_COMMS_HOST      0x00001000
+#define REG_SIZE_TOPAZ_ESB_HOST        0x00004000
+
+
+/* Topaz core registers MTX view */
+#define REG_OFFSET_TOPAZ_CORE_MTX      0x00010000      // MUST confirm
+#define REG_SIZE_TOPAZ_CORE_MTX        0x00010000      // MUST confirm
+
+#define REG_OFFSET_TOPAZ_MTX_MTX       0x00000000
+#define REG_OFFSET_TOPAZ_TOPAZ_MTX     0x00000800
+#define REG_OFFSET_TOPAZ_MVEA_MTX      0x00000C00
+#define REG_OFFSET_TOPAZ_MVEACMD_MTX   0x00001000
+#define REG_OFFSET_TOPAZ_VLC_MTX       0x00001400
+#define REG_OFFSET_TOPAZ_DEBLOCKER_MTX 0x00001800
+#define REG_OFFSET_TOPAZ_COMMS_MTX     0x00001C00
+#define REG_OFFSET_TOPAZ_ESB_MTX       0x00002000
+
+#define REG_SIZE_TOPAZ_MTX_MTX         0x00000800
+#define REG_SIZE_TOPAZ_TOPAZ_MTX       0x00000400
+#define REG_SIZE_TOPAZ_MVEA_MTX                0x00000400
+#define REG_SIZE_TOPAZ_MVEACMD_MTX     0x00000400
+#define REG_SIZE_TOPAZ_VLC_MTX         0x00000400
+#define REG_SIZE_TOPAZ_DEBLOCKER_MTX   0x00000400
+#define REG_SIZE_TOPAZ_COMMS_MTX       0x00000400
+#define REG_SIZE_TOPAZ_ESB_MTX         0x00002000
+
+
+/* Register bank addresses - Host View */
+#define REG_START_TOPAZ_MULTICORE_HOST (REG_BASE_HOST + REG_OFFSET_TOPAZ_MULTICORE)
+#define REG_END_TOPAZ_MULTICORE_HOST   (REG_START_TOPAZ_MULTICORE_HOST + REG_SIZE_TOPAZ_MULTICORE)
+
+#define REG_START_TOPAZ_DMAC_HOST      (REG_BASE_HOST + REG_OFFSET_TOPAZ_DMAC)
+#define REG_END_TOPAZ_DMAC_HOST                (REG_START_TOPAZ_DMAC_HOST + REG_SIZE_TOPAZ_DMAC)
+
+#define REG_START_TOPAZ_MTX_HOST(core) (REG_BASE_HOST + (REG_SIZE_TOPAZ_CORE_HOST*core) + REG_OFFSET_TOPAZ_CORE_HOST + REG_OFFSET_TOPAZ_MTX_HOST)
+#define REG_END_TOPAZ_MTX_HOST(core)   (REG_START_TOPAZ_MTX_HOST(core) + REG_SIZE_TOPAZ_MTX_HOST)
+
+#define REG_START_TOPAZ_TOPAZ_HOST(core)       (REG_BASE_HOST + (REG_SIZE_TOPAZ_CORE_HOST*core) + REG_OFFSET_TOPAZ_CORE_HOST + REG_OFFSET_TOPAZ_TOPAZ_HOST)
+#define REG_END_TOPAZ_TOPAZ_HOST(core) (REG_START_TOPAZ_TOPAZ_HOST(core) + REG_SIZE_TOPAZ_TOPAZ_HOST)
+
+#define REG_START_TOPAZ_MVEA_HOST(core)        (REG_BASE_HOST + (REG_SIZE_TOPAZ_CORE_HOST*core) + REG_OFFSET_TOPAZ_CORE_HOST + REG_OFFSET_TOPAZ_MVEA_HOST)
+#define REG_END_TOPAZ_MVEA_HOST(core)  (REG_START_TOPAZ_MVEA_HOST(core) + REG_SIZE_TOPAZ_MVEA_HOST)
+
+
+/* Register bank addresses - MTX view */
+#define REG_START_TOPAZ_MULTICORE_MTX  (REG_BASE_MTX + REG_OFFSET_TOPAZ_MULTICORE)
+#define REG_END_TOPAZ_MULTICORE_MTX    (REG_START_TOPAZ_MULTICORE_MTX + REG_SIZE_TOPAZ_MULTICORE)
+
+#define REG_START_TOPAZ_DMAC_MTX       (REG_BASE_MTX + REG_OFFSET_TOPAZ_DMAC)
+#define REG_END_TOPAZ_DMAC_MTX         (REG_START_TOPAZ_DMAC_MTX + REG_SIZE_TOPAZ_DMAC)
+
+#define REG_START_TOPAZ_MTX_MTX(core)  (REG_BASE_MTX + (REG_SIZE_TOPAZ_CORE_MTX*core) + REG_OFFSET_TOPAZ_CORE_MTX + REG_OFFSET_TOPAZ_MTX_MTX)
+#define REG_END_TOPAZ_MTX_MTX(core)    (REG_START_TOPAZ_MTX_MTX(core) + REG_SIZE_TOPAZ_MTX_MTX)
+
+#define REG_START_TOPAZ_TOPAZ_MTX(core)        (REG_BASE_MTX + (REG_SIZE_TOPAZ_CORE_MTX*core) + REG_OFFSET_TOPAZ_CORE_MTX + REG_OFFSET_TOPAZ_TOPAZ_MTX)
+#define REG_END_TOPAZ_TOPAZ_MTX(core)  (REG_START_TOPAZ_TOPAZ_MTX(core) + REG_SIZE_TOPAZ_TOPAZ_MTX)
+
+#define REG_START_TOPAZ_MVEA_MTX(core) (REG_BASE_MTX + (REG_SIZE_TOPAZ_CORE_MTX*core) + REG_OFFSET_TOPAZ_CORE_MTX + REG_OFFSET_TOPAZ_MVEA_MTX)
+#define REG_END_TOPAZ_MVEA_MTX(core)   (REG_START_TOPAZ_MVEA_MTX(core) + REG_SIZE_TOPAZ_MVEA_MTX)
+
+
+/* Every Topaz core has a 64K address space*/
+#define TOPAZ_CORE_REG_BASE(core) (REG_BASE_HOST + (REG_SIZE_TOPAZ_CORE_HOST*core) + REG_OFFSET_TOPAZ_CORE_HOST)
+
+/* MVEA macro */
+#define MVEA_START 0x03000
+
+#ifdef TOPAZ_PDUMP
+#define MVEA_WRITE32(offset, value, core) \
+       do { \
+               MM_WRITE32(MVEA_START + TOPAZ_CORE_REG_BASE(core), offset, value); \
+               DRM_ERROR("TOPAZ_PDUMP: MVEA core %d, REG_WT %x %x\n", core, offset, value); \
+       } while (0)
+#define MVEA_READ32(offset, pointer, core) \
+       do { \
+               MM_READ32(MVEA_START + TOPAZ_CORE_REG_BASE(core), offset, pointer); \
+               DRM_ERROR("TOPAZ_PDUMP: MVEA core %d, REG_RD %x %x\n", core, offset, *(uint32_t *)pointer);\
+       } while (0)
+#else
+#define MVEA_WRITE32(offset, value, core) \
+               MM_WRITE32(MVEA_START + TOPAZ_CORE_REG_BASE(core), offset, value)
+
+#define MVEA_READ32(offset, pointer, core) \
+               MM_READ32(MVEA_START + TOPAZ_CORE_REG_BASE(core), offset, pointer)
+#endif
+
+#define F_MASK_MVEA(basename)  (MASK_MVEA_##basename)  /*     MVEA    */
+#define F_SHIFT_MVEA(basename) (SHIFT_MVEA_##basename) /*     MVEA    */
+#define F_ENCODE_MVEA(val, basename)  \
+       (((val)<<(F_SHIFT_MVEA(basename)))&(F_MASK_MVEA(basename)))
+
+/* MVEA ESB macro */
+#define MVEA_ESB_START 0x08000
+
+#ifdef TOPAZ_PDUMP
+#define MVEA_ESB_WRITE32(offset, value, core) \
+       do { \
+               MM_WRITE32(MVEA_ESB_START + TOPAZ_CORE_REG_BASE(core),\
+                               offset, value); \
+               DRM_ERROR("TOPAZ_PDUMP: MVEA core %d, REG_WT %x %x\n", \
+                               core, offset, value); \
+       } while (0)
+#define MVEA_ESB_READ32(offset, pointer, core) \
+       do { \
+               MM_READ32(MVEA_ESB_START + TOPAZ_CORE_REG_BASE(core),\
+                               offset, pointer); \
+               DRM_ERROR("TOPAZ_PDUMP: MVEA core %d, REG_RD %x %x\n", \
+                               core, offset, *(uint32_t *)pointer);\
+       } while (0)
+#else
+#define MVEA_ESB_WRITE32(offset, value, core) \
+               MM_WRITE32(MVEA_ESB_START + TOPAZ_CORE_REG_BASE(core), \
+                               offset, value)
+
+#define MVEA_ESB_READ32(offset, pointer, core) \
+               MM_READ32(MVEA_ESB_START + TOPAZ_CORE_REG_BASE(core), \
+                               offset, pointer)
+#endif
+
+
+/* VLC macro */
+#define TOPAZ_VLC_START 0x05000
+
+/* TOPAZ macro */
+#define TOPAZ_START 0x02000
+
+#ifdef TOPAZ_PDUMP
+#define TOPAZ_WRITE32(offset, value, core) \
+       do {\
+               MM_WRITE32(TOPAZ_START + TOPAZ_CORE_REG_BASE(core), offset, value); \
+               DRM_ERROR("TOPAZ_PDUMP: TOPAZ_CORE %d REG_WT: %x %x\n", core,  \
+                        offset, value);\
+       } while (0)
+#define TOPAZ_READ32(offset, pointer, core) \
+       do { \
+               MM_READ32(TOPAZ_START + TOPAZ_CORE_REG_BASE(core), offset, pointer); \
+               DRM_ERROR("TOPAZ_PDUMP: TOPAZ_CORE %d REG_RD: %x %x\n", core, \
+                       offset, *(uint32_t *)pointer);\
+       } while (0)
+#else
+#define TOPAZ_WRITE32(offset, value, core) \
+               MM_WRITE32(TOPAZ_START + TOPAZ_CORE_REG_BASE(core), offset, value)
+#define TOPAZ_READ32(offset, pointer, core) \
+               MM_READ32(TOPAZ_START + TOPAZ_CORE_REG_BASE(core), offset, pointer)
+#endif
+#define F_MASK_TOPAZ(basename)  (MASK_TOPAZ_##basename)
+#define F_SHIFT_TOPAZ(basename) (SHIFT_TOPAZ_##basename)
+#define F_ENCODE_TOPAZ(val, basename) \
+       (((val)<<(F_SHIFT_TOPAZ(basename)))&(F_MASK_TOPAZ(basename)))
+
+/* MTX macro */
+#define MTX_START 0x0
+
+#ifdef TOPAZ_PDUMP
+#define MTX_WRITE32(offset, value, core) \
+       do { \
+               MM_WRITE32(MTX_START + TOPAZ_CORE_REG_BASE(core), offset, value); \
+               DRM_ERROR("TOPAZ_PDUMP: MTX core %d REG_WT: %x %x\n", core,\
+                       offset, value);\
+       } while (0)
+
+
+#define MTX_READ32(offset, pointer, core) \
+       do { \
+               MM_READ32(MTX_START + TOPAZ_CORE_REG_BASE(core), offset, pointer); \
+               DRM_ERROR("TOPAZ_PDUMP: MTX core %d REG_RD %x %x\n", core, \
+                       offset, *(uint32_t *)pointer); \
+       } while (0);
+#else
+
+#define MTX_WRITE32(offset, value, core) \
+               MM_WRITE32(MTX_START + TOPAZ_CORE_REG_BASE(core), offset, value)
+#define MTX_READ32(offset, pointer, core) \
+               MM_READ32(MTX_START + TOPAZ_CORE_REG_BASE(core), offset, pointer)
+#endif
+
+/* DMAC macro */
+#define DMAC_START 0x01000
+
+#ifdef TOPAZ_DUMP
+#define DMAC_WRITE32(offset, value) \
+       do { \
+                MM_WRITE32(DMAC_START, offset, value);\
+               DRM_ERROR("TOPAZ_PDUMP: DMAC WT %x %x\n", offset, value);\
+       } while (0);
+
+#define DMAC_READ32(offset, pointer) \
+       do {\
+               MM_READ32(DMAC_START, offset, pointer);\
+               DRM_ERROR("TOPAZ_PDUMP: DMAC RD %x %x\n", offset, *(uint32_t *)pointer); \
+       } while (0)
+#else
+
+#define DMAC_WRITE32(offset, value) \
+                MM_WRITE32(DMAC_START, offset, value)
+
+#define DMAC_READ32(offset, pointer) \
+               MM_READ32(DMAC_START, offset, pointer)
+#endif
+#define F_MASK_DMAC(basename)  (MASK_DMAC_##basename)
+#define F_SHIFT_DMAC(basename) (SHIFT_DMAC_##basename)
+#define F_ENCODE_DMAC(val, basename)  \
+       (((val)<<(F_SHIFT_DMAC(basename)))&(F_MASK_DMAC(basename)))
+
+/* Register CR_IMG_TOPAZ_INTENAB */
+#define TOPAZ_CR_IMG_TOPAZ_INTENAB  0x0008
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTEN_MVEA 0x00000001
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTEN_MVEA 0
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTEN_MVEA 0x0008
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX 0x00000002
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX 1
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX 0x0008
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX_HALT 0x00000004
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX_HALT 2
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX_HALT 0x0008
+
+/*(Bit 3 enables fault interrupts caused by the topaz_cores. Bit 4 enables
+ * fault interrupts caused by the DMAC)*/
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTEN_MMU_FAULT 0x00000018
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTEN_MMU_FAULT 3
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTEN_MMU_FAULT 0x0008
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_MAS_INTEN 0x80000000
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_MAS_INTEN 31
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_MAS_INTEN 0x0008
+
+#define TOPAZ_CR_IMG_TOPAZ_INTCLEAR 0x000C
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTCLR_MVEA 0x00000001
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTCLR_MVEA 0
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTCLR_MVEA 0x000C
+
+#define TOPAZ_CR_IMG_TOPAZ_INTSTAT  0x0004
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTS_MVEA 0x00000001
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTS_MVEA 0
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTS_MVEA 0x0004
+
+#define MTX_CCBCTRL_ROFF               0
+#define MTX_CCBCTRL_COMPLETE           4
+#define MTX_CCBCTRL_CCBSIZE            8
+#define MTX_CCBCTRL_QP                 12
+#define MTX_CCBCTRL_FRAMESKIP          20
+#define MTX_CCBCTRL_INITQP             24
+
+#define TOPAZ_CR_MMU_STATUS         0x001C
+#define MASK_TOPAZ_CR_MMU_PF_N_RW   0x00000001
+#define SHIFT_TOPAZ_CR_MMU_PF_N_RW  0
+#define REGNUM_TOPAZ_CR_MMU_PF_N_RW 0x001C
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTCLR_MMU_FAULT 0x00000008
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTCLR_MMU_FAULT 3
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTCLR_MMU_FAULT 0x000C
+
+#define TOPAZ_CR_MMU_MEM_REQ        0x0020
+#define MASK_TOPAZ_CR_MEM_REQ_STAT_READS 0x000000FF
+#define SHIFT_TOPAZ_CR_MEM_REQ_STAT_READS 0
+#define REGNUM_TOPAZ_CR_MEM_REQ_STAT_READS 0x0020
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX 0x00000002
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX 1
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX 0x000C
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX_HALT 0x00000004
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX_HALT 2
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX_HALT 0x000C
+
+/* Register CR_TOPAZ_CMD_FIFO_2 */
+#define TOPAZ_CR_TOPAZ_CMD_FIFO_2   0x005C
+#define MASK_TOPAZ_CR_CMD_FIFO_FLUSH 0x00000001
+#define SHIFT_TOPAZ_CR_CMD_FIFO_FLUSH 0
+#define REGNUM_TOPAZ_CR_CMD_FIFO_FLUSH 0x005C
+
+#define MTX_CR_MTX_KICK             0x0080
+#define MASK_MTX_MTX_KICK           0x0000FFFF
+#define SHIFT_MTX_MTX_KICK          0
+#define REGNUM_MTX_MTX_KICK         0x0080
+
+#define MTX_DATA_MEM_BASE              0x82880000
+
+#define MTX_CR_MTX_RAM_ACCESS_CONTROL 0x0108
+#define MASK_MTX_MTX_MCMR           0x00000001
+#define SHIFT_MTX_MTX_MCMR          0
+#define REGNUM_MTX_MTX_MCMR         0x0108
+
+#define MASK_MTX_MTX_MCMID          0x0FF00000
+#define SHIFT_MTX_MTX_MCMID         20
+#define REGNUM_MTX_MTX_MCMID        0x0108
+
+#define MASK_MTX_MTX_MCM_ADDR       0x000FFFFC
+#define SHIFT_MTX_MTX_MCM_ADDR      2
+#define REGNUM_MTX_MTX_MCM_ADDR     0x0108
+
+#define MTX_CR_MTX_RAM_ACCESS_STATUS 0x010C
+#define MASK_MTX_MTX_MTX_MCM_STAT   0x00000001
+#define SHIFT_MTX_MTX_MTX_MCM_STAT  0
+#define REGNUM_MTX_MTX_MTX_MCM_STAT 0x010C
+
+#define MASK_MTX_MTX_MCMAI          0x00000002
+#define SHIFT_MTX_MTX_MCMAI         1
+#define REGNUM_MTX_MTX_MCMAI        0x0108
+
+#define MVEA_CR_MVEA_BUSY           0x0018
+#define MVEA_CR_MVEA_DMACMDFIFO_WAIT 0x001C
+#define MVEA_CR_MVEA_DMACMDFIFO_STATUS 0x0020
+
+#define MVEA_CR_IMG_MVEA_SRST       0x0000
+#define MASK_MVEA_CR_IMG_MVEA_SPE_SOFT_RESET 0x00000001
+#define SHIFT_MVEA_CR_IMG_MVEA_SPE_SOFT_RESET 0
+#define REGNUM_MVEA_CR_IMG_MVEA_SPE_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_IPE_SOFT_RESET 0x00000002
+#define SHIFT_MVEA_CR_IMG_MVEA_IPE_SOFT_RESET 1
+#define REGNUM_MVEA_CR_IMG_MVEA_IPE_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET 0x00000004
+#define SHIFT_MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET 2
+#define REGNUM_MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET 0x00000008
+#define SHIFT_MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET 3
+#define REGNUM_MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_CMC_SOFT_RESET 0x00000010
+#define SHIFT_MVEA_CR_IMG_MVEA_CMC_SOFT_RESET 4
+#define REGNUM_MVEA_CR_IMG_MVEA_CMC_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_DCF_SOFT_RESET 0x00000020
+#define SHIFT_MVEA_CR_IMG_MVEA_DCF_SOFT_RESET 5
+#define REGNUM_MVEA_CR_IMG_MVEA_DCF_SOFT_RESET 0x0000
+
+#define TOPAZ_CR_IMG_TOPAZ_CORE_ID  0x03C0
+#define TOPAZ_CR_IMG_TOPAZ_CORE_REV 0x03D0
+
+#define TOPAZ_MTX_PC           (0x00000005)
+
+#define TOPAZ_CR_TOPAZ_AUTO_CLK_GATE 0x0014
+#define MASK_TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE 0x00000001
+#define SHIFT_TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE 0
+#define REGNUM_TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE 0x0014
+
+#define MASK_TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE 0x00000002
+#define SHIFT_TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE 1
+#define REGNUM_TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE 0x0014
+
+#define        MTX_CORE_CR_MTX_REGISTER_READ_WRITE_DATA_OFFSET 0x000000F8
+#define        MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET 0x000000FC
+#define        MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_MASK 0x00010000
+#define        MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK 0x80000000
+
+#define        TOPAZ_CORE_CR_MTX_DEBUG_OFFSET  0x00000044
+
+#define MASK_TOPAZ_CR_MTX_RAM_BANKS 0x00000F00
+#define SHIFT_TOPAZ_CR_MTX_RAM_BANKS 8
+#define REGNUM_TOPAZ_CR_MTX_RAM_BANKS 0x0044
+
+#define MASK_TOPAZ_CR_MTX_RAM_BANK_SIZE 0x000F0000
+#define SHIFT_TOPAZ_CR_MTX_RAM_BANK_SIZE 16
+#define REGNUM_TOPAZ_CR_MTX_RAM_BANK_SIZE 0x0044
+
+#define MASK_TOPAZ_CR_MTX_LAST_RAM_BANK_SIZE 0x0F000000
+#define SHIFT_TOPAZ_CR_MTX_LAST_RAM_BANK_SIZE 24
+#define REGNUM_TOPAZ_CR_MTX_LAST_RAM_BANK_SIZE 0x0044
+
+#define MASK_TOPAZ_CR_MTX_DBG_IS_SLAVE 0x00000004
+#define SHIFT_TOPAZ_CR_MTX_DBG_IS_SLAVE 2
+#define REGNUM_TOPAZ_CR_MTX_DBG_IS_SLAVE 0x003C
+
+#define MASK_TOPAZ_CR_MTX_DBG_GPIO_OUT 0x00000018
+#define SHIFT_TOPAZ_CR_MTX_DBG_GPIO_OUT 3
+#define REGNUM_TOPAZ_CR_MTX_DBG_GPIO_OUT 0x003C
+
+/* Register CR_MTX_RAM_ACCESS_DATA_EXCHANGE */
+#define MTX_CR_MTX_RAM_ACCESS_DATA_EXCHANGE 0x0100
+/* Register CR_MTX_RAM_ACCESS_DATA_TRANSFER */
+#define MTX_CR_MTX_RAM_ACCESS_DATA_TRANSFER 0x0104
+
+#define        MTX_CORE_CR_MTX_RAM_ACCESS_CONTROL_OFFSET 0x00000108
+#define MASK_MTX_MTX_MCMR           0x00000001
+#define SHIFT_MTX_MTX_MCMR          0
+#define REGNUM_MTX_MTX_MCMR         0x0108
+
+#define MASK_MTX_MTX_MCMAI          0x00000002
+#define SHIFT_MTX_MTX_MCMAI         1
+#define REGNUM_MTX_MTX_MCMAI        0x0108
+
+#define MASK_MTX_MTX_MCM_ADDR       0x000FFFFC
+#define SHIFT_MTX_MTX_MCM_ADDR      2
+#define REGNUM_MTX_MTX_MCM_ADDR     0x0108
+
+#define MASK_MTX_MTX_MCMID          0x0FF00000
+#define SHIFT_MTX_MTX_MCMID         20
+#define REGNUM_MTX_MTX_MCMID        0x0108
+
+#define TOPAZ_CR_MMU_CONTROL0       0x0024
+#define MASK_TOPAZ_CR_MMU_BYPASS_DMAC 0x00020000
+#define SHIFT_TOPAZ_CR_MMU_BYPASS_DMAC 17
+#define REGNUM_TOPAZ_CR_MMU_BYPASS_DMAC 0x0024
+
+#define MASK_TOPAZ_CR_MMU_BYPASS    0x00010000
+#define SHIFT_TOPAZ_CR_MMU_BYPASS   16
+#define REGNUM_TOPAZ_CR_MMU_BYPASS  0x0024
+
+#define TOPAZ_CR_MMU_DIR_LIST_BASE(X) (0x0030 + (4 * (X)))
+#define MASK_TOPAZ_CR_MMU_DIR_LIST_BASE_ADDR 0xFFFFF000
+#define SHIFT_TOPAZ_CR_MMU_DIR_LIST_BASE_ADDR 12
+#define REGNUM_TOPAZ_CR_MMU_DIR_LIST_BASE_ADDR 0x0030
+
+#define MASK_TOPAZ_CR_MMU_INVALDC   0x00000008
+#define SHIFT_TOPAZ_CR_MMU_INVALDC  3
+#define REGNUM_TOPAZ_CR_MMU_INVALDC 0x0024
+
+#define MASK_TOPAZ_CR_MMU_FLUSH     0x00000004
+#define SHIFT_TOPAZ_CR_MMU_FLUSH    2
+#define REGNUM_TOPAZ_CR_MMU_FLUSH   0x0024
+
+#define TOPAZ_CR_MMU_CONTROL1       0x0028
+
+/* Register CR_MMU_BANK_INDEX */
+#define TOPAZ_CR_MMU_BANK_INDEX     0x0040
+#define MASK_TOPAZ_CR_MMU_BANK_N_INDEX_M(i) (0x00000003 << (8 + ((i) * 2)))
+#define SHIFT_TOPAZ_CR_MMU_BANK_N_INDEX_M(i) (8 + ((i) * 2))
+#define REGNUM_TOPAZ_CR_MMU_BANK_N_INDEX_M(i) 0x0040
+
+#define MASK_TOPAZ_CR_MMU_BANK_SELECT(i) (0x00000001 << (0 + ((i) * 1)))
+#define SHIFT_TOPAZ_CR_MMU_BANK_SELECT(i) (0 + ((i) * 1))
+#define REGNUM_TOPAZ_CR_MMU_BANK_SELECT(i) 0x0040
+
+#define TOPAZ_CR_TOPAZ_MAN_CLK_GATE 0x0010
+#define MASK_TOPAZ_CR_TOPAZ_MTX_MAN_CLK_GATE 0x00000002
+#define SHIFT_TOPAZ_CR_TOPAZ_MTX_MAN_CLK_GATE 1
+#define REGNUM_TOPAZ_CR_TOPAZ_MTX_MAN_CLK_GATE 0x0010
+
+#define MTX_CORE_CR_MTX_TXRPT_OFFSET 0x0000000c
+#define TXRPT_WAITONKICK_VALUE 0x8ade0000
+
+#define MTX_CORE_CR_MTX_ENABLE_MTX_TOFF_MASK 0x00000002
+
+#define MTX_CORE_CR_MTX_ENABLE_OFFSET 0x00000000
+#define        MTX_CORE_CR_MTX_ENABLE_MTX_ENABLE_MASK 0x00000001
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTS_MTX 0x00000002
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTS_MTX 1
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTS_MTX 0x0004
+
+#define        MTX_CORE_CR_MTX_SOFT_RESET_OFFSET 0x00000200
+#define        MTX_CORE_CR_MTX_SOFT_RESET_MTX_RESET_MASK 0x00000001
+
+#define MTX_CR_MTX_SYSC_CDMAA       0x0344
+#define MASK_MTX_CDMAA_ADDRESS      0x03FFFFFC
+#define SHIFT_MTX_CDMAA_ADDRESS     2
+#define REGNUM_MTX_CDMAA_ADDRESS    0x0344
+
+#define MTX_CR_MTX_SYSC_CDMAC       0x0340
+#define MASK_MTX_LENGTH             0x0000FFFF
+#define SHIFT_MTX_LENGTH            0
+#define REGNUM_MTX_LENGTH           0x0340
+
+#define MASK_MTX_BURSTSIZE          0x07000000
+#define SHIFT_MTX_BURSTSIZE         24
+#define REGNUM_MTX_BURSTSIZE        0x0340
+
+#define MASK_MTX_RNW                0x00020000
+#define SHIFT_MTX_RNW               17
+#define REGNUM_MTX_RNW              0x0340
+
+#define MASK_MTX_ENABLE             0x00010000
+#define SHIFT_MTX_ENABLE            16
+#define REGNUM_MTX_ENABLE           0x0340
+
+#define MASK_MTX_LENGTH             0x0000FFFF
+#define SHIFT_MTX_LENGTH            0
+#define REGNUM_MTX_LENGTH           0x0340
+
+#define TOPAZ_CR_IMG_TOPAZ_SRST     0x0000
+#define MASK_TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET 0x00000001
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET 0
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET 0x0000
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET 0x00000004
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET 2
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET 0x0000
+#define SIGNED_TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET 0
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET 0x00000008
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET 3
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET 0x0000
+#define SIGNED_TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET 0
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET 0x00000010
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET 4
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET 0x0000
+#define SIGNED_TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET 0
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET 0x00000002
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET 1
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET 0x0000
+
+#define MVEA_CR_MVEA_AUTO_CLOCK_GATING 0x0024
+#define MASK_MVEA_CR_MVEA_SPE_AUTO_CLK_GATE 0x00000001
+#define SHIFT_MVEA_CR_MVEA_SPE_AUTO_CLK_GATE 0
+#define REGNUM_MVEA_CR_MVEA_SPE_AUTO_CLK_GATE 0x0024
+
+#define MASK_MVEA_CR_MVEA_IPE_AUTO_CLK_GATE 0x00000002
+#define SHIFT_MVEA_CR_MVEA_IPE_AUTO_CLK_GATE 1
+#define REGNUM_MVEA_CR_MVEA_IPE_AUTO_CLK_GATE 0x0024
+
+#define MASK_MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE 0x00000004
+#define SHIFT_MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE 2
+#define REGNUM_MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE 0x0024
+
+#define MASK_MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE 0x00000008
+#define SHIFT_MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE 3
+#define REGNUM_MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE 0x0024
+
+/*#define TOPAZ_CR_IMG_TOPAZ_DMAC_MODE 0x0040
+#define MASK_TOPAZ_CR_DMAC_MASTER_MODE 0x00000001
+#define SHIFT_TOPAZ_CR_DMAC_MASTER_MODE 0
+#define REGNUM_TOPAZ_CR_DMAC_MASTER_MODE 0x0040*/
+
+/* Register CR_TOPAZ_HW_CFG */
+#define TOPAZ_CR_TOPAZ_HW_CFG       0x0050
+#define MASK_TOPAZ_CR_NUM_CORES_SUPPORTED 0x0000001F
+#define SHIFT_TOPAZ_CR_NUM_CORES_SUPPORTED 0
+#define REGNUM_TOPAZ_CR_NUM_CORES_SUPPORTED 0x0050
+
+/* Register CR_TOPAZ_CMD_FIFO_0 */
+#define TOPAZ_CR_TOPAZ_CMD_FIFO_0   0x0054
+#define MASK_TOPAZ_CR_CMD_FIFO_RDATA 0xFFFFFFFF
+#define SHIFT_TOPAZ_CR_CMD_FIFO_RDATA 0
+#define REGNUM_TOPAZ_CR_CMD_FIFO_RDATA 0x0054
+
+/* Register CR_TOPAZ_CMD_FIFO_1 */
+#define TOPAZ_CR_TOPAZ_CMD_FIFO_1   0x0058
+#define MASK_TOPAZ_CR_CMD_FIFO_QUANTITY 0x000000FF
+#define SHIFT_TOPAZ_CR_CMD_FIFO_QUANTITY 0
+#define REGNUM_TOPAZ_CR_CMD_FIFO_QUANTITY 0x0058
+
+#define MASK_TOPAZ_CR_CMD_FIFO_NOTEMPTY 0x00000100
+#define SHIFT_TOPAZ_CR_CMD_FIFO_NOTEMPTY 8
+#define REGNUM_TOPAZ_CR_CMD_FIFO_NOTEMPTY 0x0058
+
+/* Register CR_TOPAZ_CMD_FIFO_2 */
+#define TOPAZ_CR_TOPAZ_CMD_FIFO_2   0x005C
+#define MASK_TOPAZ_CR_CMD_FIFO_FLUSH 0x00000001
+#define SHIFT_TOPAZ_CR_CMD_FIFO_FLUSH 0
+#define REGNUM_TOPAZ_CR_CMD_FIFO_FLUSH 0x005C
+
+#define MTX_CR_MTX_SYSC_CDMAT       0x0350
+#define MASK_MTX_TRANSFERDATA       0xFFFFFFFF
+#define SHIFT_MTX_TRANSFERDATA      0
+#define REGNUM_MTX_TRANSFERDATA     0x0350
+
+#define IMG_SOC_DMAC_IRQ_STAT(X)    (0x000C + (32 * (X)))
+#define MASK_IMG_SOC_TRANSFER_FIN   0x00020000
+#define SHIFT_IMG_SOC_TRANSFER_FIN  17
+#define REGNUM_IMG_SOC_TRANSFER_FIN 0x000C
+
+#define IMG_SOC_DMAC_COUNT(X)       (0x0004 + (32 * (X)))
+#define MASK_IMG_SOC_CNT            0x0000FFFF
+#define SHIFT_IMG_SOC_CNT           0
+#define REGNUM_IMG_SOC_CNT          0x0004
+
+#define MASK_IMG_SOC_EN             0x00010000
+#define SHIFT_IMG_SOC_EN            16
+#define REGNUM_IMG_SOC_EN           0x0004
+
+#define MASK_IMG_SOC_LIST_EN        0x00040000
+#define SHIFT_IMG_SOC_LIST_EN       18
+#define REGNUM_IMG_SOC_LIST_EN      0x0004
+
+#define IMG_SOC_DMAC_PER_HOLD(X)    (0x0018 + (32 * (X)))
+#define MASK_IMG_SOC_PER_HOLD       0x0000007F
+#define SHIFT_IMG_SOC_PER_HOLD      0
+#define REGNUM_IMG_SOC_PER_HOLD     0x0018
+
+#define IMG_SOC_DMAC_SETUP(X)       (0x0000 + (32 * (X)))
+#define MASK_IMG_SOC_START_ADDRESS  0xFFFFFFF
+#define SHIFT_IMG_SOC_START_ADDRESS 0
+#define REGNUM_IMG_SOC_START_ADDRESS 0x0000
+
+#define MASK_IMG_SOC_BSWAP          0x40000000
+#define SHIFT_IMG_SOC_BSWAP         30
+#define REGNUM_IMG_SOC_BSWAP        0x0004
+
+#define MASK_IMG_SOC_PW             0x18000000
+#define SHIFT_IMG_SOC_PW            27
+#define REGNUM_IMG_SOC_PW           0x0004
+
+#define MASK_IMG_SOC_DIR            0x04000000
+#define SHIFT_IMG_SOC_DIR           26
+#define REGNUM_IMG_SOC_DIR          0x0004
+
+#define MASK_IMG_SOC_PI             0x03000000
+#define SHIFT_IMG_SOC_PI            24
+#define REGNUM_IMG_SOC_PI           0x0004
+#define IMG_SOC_PI_1           0x00000002
+#define IMG_SOC_PI_2           0x00000001
+#define IMG_SOC_PI_4           0x00000000
+
+#define MASK_IMG_SOC_TRANSFER_IEN   0x20000000
+#define SHIFT_IMG_SOC_TRANSFER_IEN  29
+#define REGNUM_IMG_SOC_TRANSFER_IEN 0x0004
+
+#define DMAC_VALUE_COUNT(BSWAP, PW, DIR, PERIPH_INCR, COUNT)        \
+       ((((BSWAP) << SHIFT_IMG_SOC_BSWAP) & MASK_IMG_SOC_BSWAP)|       \
+               (((PW) << SHIFT_IMG_SOC_PW) & MASK_IMG_SOC_PW)|         \
+               (((DIR) << SHIFT_IMG_SOC_DIR) & MASK_IMG_SOC_DIR)|      \
+               (((PERIPH_INCR) << SHIFT_IMG_SOC_PI) & MASK_IMG_SOC_PI)| \
+               (((COUNT) << SHIFT_IMG_SOC_CNT) & MASK_IMG_SOC_CNT))
+
+#define IMG_SOC_DMAC_PERIPH(X)      (0x0008 + (32 * (X)))
+#define MASK_IMG_SOC_EXT_SA         0x0000000F
+#define SHIFT_IMG_SOC_EXT_SA        0
+#define REGNUM_IMG_SOC_EXT_SA       0x0008
+
+#define MASK_IMG_SOC_ACC_DEL        0xE0000000
+#define SHIFT_IMG_SOC_ACC_DEL       29
+#define REGNUM_IMG_SOC_ACC_DEL      0x0008
+
+#define MASK_IMG_SOC_INCR           0x08000000
+#define SHIFT_IMG_SOC_INCR          27
+#define REGNUM_IMG_SOC_INCR         0x0008
+
+#define MASK_IMG_SOC_BURST          0x07000000
+#define SHIFT_IMG_SOC_BURST         24
+#define REGNUM_IMG_SOC_BURST        0x0008
+
+#define DMAC_VALUE_PERIPH_PARAM(ACC_DEL, INCR, BURST)             \
+((((ACC_DEL) << SHIFT_IMG_SOC_ACC_DEL) & MASK_IMG_SOC_ACC_DEL)|        \
+(((INCR) << SHIFT_IMG_SOC_INCR) & MASK_IMG_SOC_INCR)|             \
+(((BURST) << SHIFT_IMG_SOC_BURST) & MASK_IMG_SOC_BURST))
+
+#define IMG_SOC_DMAC_PERIPHERAL_ADDR(X) (0x0014 + (32 * (X)))
+#define MASK_IMG_SOC_ADDR           0x007FFFFF
+#define SHIFT_IMG_SOC_ADDR          0
+#define REGNUM_IMG_SOC_ADDR         0x0014
+
+#define SHIFT_TOPAZ_VEC_BUSY        11
+#define MASK_TOPAZ_VEC_BUSY         (0x1<<SHIFT_TOPAZ_VEC_BUSY)
+
+#define TOPAZ_MTX_TXRPT_OFFSET         0xc
+#define TOPAZ_GUNIT_GVD_PSMI_GFX_OFFSET 0x20D0
+
+#define TOPAZ_GUNIT_READ32(offset)  ioread32(dev_priv->vdc_reg + offset)
+#define TOPAZ_READ_BITS(val, basename) \
+               (((val)&MASK_TOPAZ_##basename)>>SHIFT_TOPAZ_##basename)
+
+#define TOPAZ_WAIT_UNTIL_IDLE \
+    do { \
+       uint8_t tmp_poll_number = 0;\
+       uint32_t tmp_reg; \
+       if (topaz_priv->topaz_cmd_windex == WB_CCB_CTRL_RINDEX(dev_priv)) { \
+               tmp_reg = TOPAZ_GUNIT_READ32(TOPAZ_GUNIT_GVD_PSMI_GFX_OFFSET);\
+               if (0 != TOPAZ_READ_BITS(tmp_reg, VEC_BUSY)) { \
+                       MTX_READ32(TOPAZ_MTX_TXRPT_OFFSET, &tmp_reg);\
+                       while ((tmp_reg != 0x8ade0000) && \
+                              (tmp_poll_number++ < 10)) \
+                               MTX_READ32(0xc, &tmp_reg); \
+                       PSB_DEBUG_GENERAL(      \
+                         "TOPAZ: TXRPT reg remain: %x,poll %d times.\n",\
+                         tmp_reg, tmp_poll_number);\
+               } \
+       } \
+    } while (0)
+
+/* Register CR_BUFFER_SIDEBAND */
+#define MVEA_CR_BUFFER_SIDEBAND     0x017C
+#define MASK_MVEA_CR_CURR_MB_SBAND  0x00000003
+#define SHIFT_MVEA_CR_CURR_MB_SBAND 0
+#define REGNUM_MVEA_CR_CURR_MB_SBAND 0x017C
+
+#define MASK_MVEA_CR_ABOVE_PIX_IN_SBAND 0x0000000C
+#define SHIFT_MVEA_CR_ABOVE_PIX_IN_SBAND 2
+#define REGNUM_MVEA_CR_ABOVE_PIX_IN_SBAND 0x017C
+
+#define MASK_MVEA_CR_CURR_PARAM_SBAND 0x00000030
+#define SHIFT_MVEA_CR_CURR_PARAM_SBAND 4
+#define REGNUM_MVEA_CR_CURR_PARAM_SBAND 0x017C
+
+#define MASK_MVEA_CR_BELOW_PARAM_IN_SBAND 0x000000C0
+#define SHIFT_MVEA_CR_BELOW_PARAM_IN_SBAND 6
+#define REGNUM_MVEA_CR_BELOW_PARAM_IN_SBAND 0x017C
+
+#define MASK_MVEA_CR_ABOVE_PARAM_IN_SBAND 0x00000300
+#define SHIFT_MVEA_CR_ABOVE_PARAM_IN_SBAND 8
+#define REGNUM_MVEA_CR_ABOVE_PARAM_IN_SBAND 0x017C
+
+#define MASK_MVEA_CR_REF_SBAND      0x00000C00
+#define SHIFT_MVEA_CR_REF_SBAND     10
+#define REGNUM_MVEA_CR_REF_SBAND    0x017C
+
+#define MASK_MVEA_CR_RECON_SBAND    0x00003000
+#define SHIFT_MVEA_CR_RECON_SBAND   12
+#define REGNUM_MVEA_CR_RECON_SBAND  0x017C
+
+#define MASK_MVEA_CR_ABOVE_PIX_OUT_SBAND 0x0000C000
+#define SHIFT_MVEA_CR_ABOVE_PIX_OUT_SBAND 14
+#define REGNUM_MVEA_CR_ABOVE_PIX_OUT_SBAND 0x017C
+
+#define MASK_MVEA_CR_BELOW_PARAM_OUT_SBAND 0x00030000
+#define SHIFT_MVEA_CR_BELOW_PARAM_OUT_SBAND 16
+#define REGNUM_MVEA_CR_BELOW_PARAM_OUT_SBAND 0x017C
+
+#define MASK_MVEA_CR_ABOVE_PARAM_OUT_SBAND 0x000C0000
+#define SHIFT_MVEA_CR_ABOVE_PARAM_OUT_SBAND 18
+#define REGNUM_MVEA_CR_ABOVE_PARAM_OUT_SBAND 0x017C
+
+/* Register CR_IPE_JITTER_FACTOR */
+#define MVEA_CR_IPE_JITTER_FACTOR   0x0218
+#define MASK_MVEA_CR_IPE_JITTER_FACTOR 0x00000003
+#define SHIFT_MVEA_CR_IPE_JITTER_FACTOR 0
+#define REGNUM_MVEA_CR_IPE_JITTER_FACTOR 0x0218
+
+/* Register CR_MULTICORE_INT_STAT */
+#define TOPAZSC_CR_MULTICORE_INT_STAT 0x0000
+#define MASK_TOPAZSC_CR_INT_STAT_DMAC 0x80000000
+#define SHIFT_TOPAZSC_CR_INT_STAT_DMAC 31
+#define REGNUM_TOPAZSC_CR_INT_STAT_DMAC 0x0000
+
+#define MASK_TOPAZSC_CR_INT_STAT_CORES 0x7FFFFFFF
+#define SHIFT_TOPAZSC_CR_INT_STAT_CORES 0
+#define REGNUM_TOPAZSC_CR_INT_STAT_CORES 0x0000
+
+/* Register CR_MULTICORE_CORE_SEL_0 */
+#define TOPAZSC_CR_MULTICORE_CORE_SEL_0 0x0004
+#define MASK_TOPAZSC_CR_DMAC_CORE_SELECT 0x0000000F
+#define SHIFT_TOPAZSC_CR_DMAC_CORE_SELECT 0
+#define REGNUM_TOPAZSC_CR_DMAC_CORE_SELECT 0x0004
+
+#define MASK_TOPAZSC_CR_WRITES_CORE_ALL 0x80000000
+#define SHIFT_TOPAZSC_CR_WRITES_CORE_ALL 31
+#define REGNUM_TOPAZSC_CR_WRITES_CORE_ALL 0x0004
+
+/* Register CR_MULTICORE_CORE_SEL_1 */
+#define TOPAZSC_CR_MULTICORE_CORE_SEL_1 0x0008
+#define MASK_TOPAZSC_CR_RTM_PORT_CORE_SELECT 0x0000000F
+#define SHIFT_TOPAZSC_CR_RTM_PORT_CORE_SELECT 0
+#define REGNUM_TOPAZSC_CR_RTM_PORT_CORE_SELECT 0x0008
+
+/* Register CR_MULTICORE_RSVD0 */
+#define TOPAZSC_CR_MULTICORE_RSVD0  0x0010
+#define MASK_TOPAZSC_CR_RESERVED0   0xFFFFFFFF
+#define SHIFT_TOPAZSC_CR_RESERVED0  0
+#define REGNUM_TOPAZSC_CR_RESERVED0 0x0010
+
+/* Register CR_MULTICORE_CMD_FIFO_0 */
+#define TOPAZSC_CR_MULTICORE_CMD_FIFO_0 0x0014
+#define MASK_TOPAZSC_CR_CMD_FIFO_WDATA 0xFFFFFFFF
+#define SHIFT_TOPAZSC_CR_CMD_FIFO_WDATA 0
+#define REGNUM_TOPAZSC_CR_CMD_FIFO_WDATA 0x0014
+
+/* Register CR_MULTICORE_CMD_FIFO_1 */
+#define TOPAZSC_CR_MULTICORE_CMD_FIFO_1 0x0018
+#define MASK_TOPAZSC_CR_CMD_FIFO_SPACE 0x000000FF
+#define SHIFT_TOPAZSC_CR_CMD_FIFO_SPACE 0
+#define REGNUM_TOPAZSC_CR_CMD_FIFO_SPACE 0x0018
+
+#define MASK_TOPAZSC_CR_CMD_FIFO_FULL 0x00000100
+#define SHIFT_TOPAZSC_CR_CMD_FIFO_FULL 8
+#define REGNUM_TOPAZSC_CR_CMD_FIFO_FULL 0x0018
+
+/* Register CR_MULTICORE_IDLE_PWR_MAN */
+#define TOPAZSC_CR_MULTICORE_IDLE_PWR_MAN 0x001C
+#define MASK_TOPAZSC_CR_TOPAZ_IDLE_DISABLE 0x00000001
+#define SHIFT_TOPAZSC_CR_TOPAZ_IDLE_DISABLE 0
+#define REGNUM_TOPAZSC_CR_TOPAZ_IDLE_DISABLE 0x001C
+
+/* Register CR_CMC_PROC_ESB_ACCESS */
+#define MVEA_CR_CMC_PROC_ESB_ACCESS 0x011C
+#define MASK_MVEA_CR_CMC_PROC_ESB_REGION_NUMBER 0x0000001F
+#define SHIFT_MVEA_CR_CMC_PROC_ESB_REGION_NUMBER 0
+#define REGNUM_MVEA_CR_CMC_PROC_ESB_REGION_NUMBER 0x011C
+#define SIGNED_MVEA_CR_CMC_PROC_ESB_REGION_NUMBER 0
+
+
+/* Table CR_CMC_ESB_LOGICAL_REGION_SETUP_TABLE */
+
+/* Register CR_CMC_ESB_LOGICAL_REGION_SETUP */
+#define MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP(X) (0x0080 + (4 * (X)))
+#define MASK_MVEA_CR_CMC_ESB_REGION_VALID 0x80000000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_VALID 31
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_VALID 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_VALID 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_TYPE 0x60000000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_TYPE 29
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_TYPE 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_TYPE 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH 0x00F00000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH 20
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_LOGICAL_OFFSET_X 0x000F0000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_LOGICAL_OFFSET_X 16
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_LOGICAL_OFFSET_X 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_LOGICAL_OFFSET_X 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT 0x0000F000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT 12
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH 0x00000F00
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH 8
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y 0x000000F0
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y 4
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X 0x0000000F
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X 0
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X 0
+
+
+/* Bit 31:16 is the count of remaining items to be transferred */
+/* Bit 0 is 1 if transfer State == 'do_nothing'*/
+#define MTX_CR_MTX_SYSC_CDMAS0      0x0348
+
+/* Bit 25:2 is the current core DMA transfer address.*/
+#define MTX_CR_MTX_SYSC_CDMAS1      0x034C
+
+/* Bit 31:0 is the data to be wroten */
+#define MTX_CR_MTX_SYSC_CDMAT       0x0350
+
+/* Number of entries in table CR_CMC_ESB_LOGICAL_REGION_SETUP_TABLE */
+
+#define MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP_TABLE_SIZE_UINT32 32
+#define MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP_TABLE_NUM_ENTRIES 32
+
+#define ESB_HWSYNC      10
+#define ESB_POS_MANGLER_ORIGINX(x) ((x) >> 3)
+#define ESB_POS_MANGLER(x) ((x) >> 3)
+
+#define ESB_SIZE_MANGLER(x) (((x) >> 3) - 1)
+#define REGION_TYPE_LINEAR 0
+
+#define TOPAZSC_ESB_REGION_Y_MAX               (46)
+#define TOPAZSC_ESB_REGION_X_MAX               (64)
+
+#define TOPAZSC_ESB_REGION_HEIGH               (48)
+#define TOPAZSC_ESB_REGION_WIDTH               (64)
+
+
+#define REG_OFFSET_COMMS_CORE_HOST     0x00070000
+#define REG_SIZE_COMMS_CORE_HOST       0x00070000
+#define REG_OFFSET_TOPAZ_COMMS_HOST    0x00007000
+#define REG_SIZE_TOPAZ_COMMS_HOST      0x00001000
+#define TOPAZ_COMMS_START 0x07000
+/* Register CR_STAT_1 */
+#define TOPAZ_COMMS_CR_STAT_1(X)    (0x0018 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_STAT_DATA_1 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_STAT_DATA_1 0
+#define REGNUM_TOPAZ_COMMS_CR_STAT_DATA_1 0x0018
+
+/* Register CR_STAT_0 */
+#define TOPAZ_COMMS_CR_STAT_0(X)    (0x0014 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_STAT_DATA_0 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_STAT_DATA_0 0
+#define REGNUM_TOPAZ_COMMS_CR_STAT_DATA_0 0x0014
+
+/* Register CR_MTX_STATUS */
+#define TOPAZ_COMMS_CR_MTX_STATUS(X) (0x0010 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_FLAGS_WORD 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_FLAGS_WORD 0
+#define REGNUM_TOPAZ_COMMS_FLAGS_WORD 0x0010
+
+/* Register CR_CMD_WB_VAL */
+#define TOPAZ_COMMS_CR_CMD_WB_VAL(X) (0x000C + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_WB_VAL  0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_WB_VAL 0
+#define REGNUM_TOPAZ_COMMS_CR_WB_VAL 0x000C
+
+/* Register CR_CMD_WB_ADDR */
+#define TOPAZ_COMMS_CR_CMD_WB_ADDR(X) (0x0008 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_WB_ADDR 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_WB_ADDR 0
+#define REGNUM_TOPAZ_COMMS_CR_WB_ADDR 0x0008
+
+/* Register CR_CMD_DATA_ADDR */
+#define TOPAZ_COMMS_CR_CMD_DATA_ADDR(X) (0x0004 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_DATA_ADDR 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_DATA_ADDR 0
+#define REGNUM_TOPAZ_COMMS_CR_DATA_ADDR 0x0004
+/* Register CR_TOPAZ_HW_CFG */
+#define TOPAZ_CR_TOPAZ_HW_CFG       0x0050
+#define MASK_TOPAZ_CR_NUM_CORES_SUPPORTED 0x0000001F
+#define SHIFT_TOPAZ_CR_NUM_CORES_SUPPORTED 0
+#define REGNUM_TOPAZ_CR_NUM_CORES_SUPPORTED 0x0050
+/* Register CR_CMD_WORD */
+#define TOPAZ_COMMS_CR_CMD_WORD(X)  (0x0000 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_MTX_CMD_ID 0x0000007F
+#define SHIFT_TOPAZ_COMMS_CR_MTX_CMD_ID 0
+#define REGNUM_TOPAZ_COMMS_CR_MTX_CMD_ID 0x0000
+#define MTX_CR_MTX_SYSC_CDMAT       0x0350
+#define MASK_MTX_TRANSFERDATA       0xFFFFFFFF
+#define SHIFT_MTX_TRANSFERDATA      0
+#define REGNUM_MTX_TRANSFERDATA     0x0350
+
+
+#define COMMS_WRITE32(offset, value, core) \
+               MM_WRITE32(TOPAZ_COMMS_START + TOPAZ_CORE_REG_BASE(core), \
+                               offset, value)
+#define COMMS_READ32(offset, pointer, core) \
+               MM_READ32(TOPAZ_COMMS_START + TOPAZ_CORE_REG_BASE(core), \
+                               offset, pointer)
+
+#define TOPAZ_CORE_NUMBER_SET_OFFSET (0x100 + (2 << 2))
+
+#define REG_SIZE_COMMS_CORE_HOST       0x00070000
+#define MVEASETUPESBREGION(_OriginX_, _OriginY_, _PhysWidth_,\
+               _PhysHeight_, _LogWidth_, _RegType_)\
+((F_ENCODE(ESB_POS_MANGLER_ORIGINX(_OriginX_),\
+          MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X))\
+ | (F_ENCODE(ESB_POS_MANGLER(_OriginY_),\
+                MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y))\
+ | (F_ENCODE(ESB_SIZE_MANGLER(_PhysWidth_),\
+                MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH))\
+ | (F_ENCODE(ESB_SIZE_MANGLER(_PhysHeight_),\
+                MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT))\
+ | (F_ENCODE(ESB_SIZE_MANGLER(_LogWidth_),\
+                MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH))\
+ | (F_ENCODE(_RegType_, MVEA_CR_CMC_ESB_REGION_TYPE))\
+ | (F_ENCODE(1, MVEA_CR_CMC_ESB_REGION_VALID)))
+
+
+#define TOPAZ_MULTICORE_START          0x00000000
+
+#ifdef TOPAZ_PDUMP
+#define TOPAZ_MULTICORE_WRITE32(offset, value) \
+       do { \
+               MM_WRITE32(TOPAZ_MULTICORE_START, offset, value); \
+               DRM_ERROR("TOPAZ_PDUMP: MULTICORE, REG_WT %x %x\n", offset, value);\
+       } while (0)
+
+#define TOPAZ_MULTICORE_READ32(offset,pointer) \
+       do { \
+               MM_READ32(TOPAZ_MULTICORE_START, offset, pointer); \
+               DRM_ERROR("TOPAZ_PDUMP: MULTICORE, REG_RD %x %x\n", offset, *(uint32_t *)pointer); \
+       } while (0)
+#else
+#define TOPAZ_MULTICORE_WRITE32(offset, value) \
+       MM_WRITE32(TOPAZ_MULTICORE_START, offset, value)
+#define TOPAZ_MULTICORE_READ32(offset,pointer) \
+       MM_READ32(TOPAZ_MULTICORE_START, offset, pointer)
+#endif
+
+#define MTX_DMA_BURSTSIZE_BYTES 32
+#define MTX_DMA_ALIGNMENT_BYTES 16
+
+#define MTX_DMA_MEMORY_BASE (0x82880000)
+#define PC_START_ADDRESS    (0x80900000)
+
+#define MAX_TOPAZ_CMD_COUNT    (0x1000) /* max syncStatus value used*/
+
+
+#define MTX_WRITEBACK_DATASIZE_ROUND 4
+
+#define TOPAZ_MTX_WB_READ32(base, core, word, pointer) \
+    do { \
+       *(uint32_t *)(pointer) = *((uint32_t *)(base) + \
+               (core)*MTX_WRITEBACK_DATASIZE_ROUND + (word) ); \
+    } while (0)
+
+#define TOPAZ_MTX_WB_WRITE32(base, core, word, value) \
+    do { \
+        *((uint32_t *)(base) + (core)*MTX_WRITEBACK_DATASIZE_ROUND + (word) ) \
+           = value; \
+    } while (0)
+
+
+#define TOPAZ_MTX_WB_OFFSET(base, core) \
+    ((base) + (core)*MTX_WRITEBACK_DATASIZE_ROUND*4)
+
+#define POLL_TOPAZ_FREE_FIFO_SPACE(word_num, delay, retries, pointer) \
+    do { \
+       uint32_t free_space=0, i; \
+       for (i = 0; i < retries; i++) {\
+           TOPAZ_MULTICORE_READ32(TOPAZSC_CR_MULTICORE_CMD_FIFO_1, &free_space);\
+           free_space &= MASK_TOPAZSC_CR_CMD_FIFO_SPACE; \
+           if (free_space >= word_num) \
+               break; \
+           else \
+               PSB_UDELAY(delay);\
+       }\
+       if ( i >= retries){ \
+           ret  = -1;\
+           DRM_ERROR("TOPAZ: poll FIFO free space failed (%d words free)!\n", free_space); \
+       }\
+       else \
+           ret = 0; \
+       *pointer = free_space; \
+    } while (0)
+
+
+/* **************** DMAC define **************** */
+enum  DMAC_eBSwap {
+       DMAC_BSWAP_NO_SWAP = 0x0,/* !< No byte swapping will be performed. */
+       DMAC_BSWAP_REVERSE = 0x1,/* !< Byte order will be reversed. */
+};
+
+enum DMAC_ePW {
+       DMAC_PWIDTH_32_BIT = 0x0,/* !< Peripheral width 32-bit. */
+       DMAC_PWIDTH_16_BIT = 0x1,/* !< Peripheral width 16-bit. */
+       DMAC_PWIDTH_8_BIT = 0x2,/* !< Peripheral width 8-bit. */
+};
+
+enum DMAC_eAccDel {
+       DMAC_ACC_DEL_0 = 0x0,   /* !< Access delay zero clock cycles */
+       DMAC_ACC_DEL_256 = 0x1, /* !< Access delay 256 clock cycles */
+       DMAC_ACC_DEL_512 = 0x2, /* !< Access delay 512 clock cycles */
+       DMAC_ACC_DEL_768 = 0x3, /* !< Access delay 768 clock cycles */
+       DMAC_ACC_DEL_1024 = 0x4,/* !< Access delay 1024 clock cycles */
+       DMAC_ACC_DEL_1280 = 0x5,/* !< Access delay 1280 clock cycles */
+       DMAC_ACC_DEL_1536 = 0x6,/* !< Access delay 1536 clock cycles */
+       DMAC_ACC_DEL_1792 = 0x7,/* !< Access delay 1792 clock cycles */
+};
+
+enum  DMAC_eBurst {
+       DMAC_BURST_0 = 0x0,     /* !< burst size of 0 */
+       DMAC_BURST_1 = 0x1,     /* !< burst size of 1 */
+       DMAC_BURST_2 = 0x2,     /* !< burst size of 2 */
+       DMAC_BURST_3 = 0x3,     /* !< burst size of 3 */
+       DMAC_BURST_4 = 0x4,     /* !< burst size of 4 */
+       DMAC_BURST_5 = 0x5,     /* !< burst size of 5 */
+       DMAC_BURST_6 = 0x6,     /* !< burst size of 6 */
+       DMAC_BURST_7 = 0x7,     /* !< burst size of 7 */
+};
+
+/* commands for topaz,shared with user space driver */
+enum drm_pnw_topaz_cmd {
+       MTX_CMDID_NULL = 0,
+       MTX_CMDID_SHUTDOWN = 1,
+       MTX_CMDID_START_PIC = 2,
+       MTX_CMDID_DO_HEADER = 3,
+       MTX_CMDID_ENCODE_SLICE = 4,
+       MTX_CMDID_END_PIC = 5,
+       MTX_CMDID_FLUSH = 6,
+       /*JPEG commands*/
+       MTX_CMDID_SETQUANT = 7,
+       MTX_CMDID_RESET_ENCODE = 8,
+       MTX_CMDID_ISSUEBUFF = 9,
+       MTX_CMDID_SETUP = 10,
+
+       MTX_CMDID_PAD = 0x7a, /*Will be ignored*/
+       MTX_CMDID_SW_WRITEREG = 0x7b,
+       MTX_CMDID_SW_LEAVE_LOWPOWER = 0x7c,
+       MTX_CMDID_SW_ENTER_LOWPOWER = 0x7e,
+       MTX_CMDID_SW_NEW_CODEC = 0x7f
+};
+
+struct topaz_cmd_header {
+       union {
+               struct {
+                       unsigned long id: 7;
+                       unsigned long enable_interrupt: 1;
+                       unsigned long core: 8;
+                       unsigned long seq: 16;
+               };
+               uint32_t val;
+       };
+};
+
+/* codecs topaz supports,shared with user space driver */
+enum drm_pnw_topaz_codec {
+       IMG_CODEC_JPEG = 0,
+       IMG_CODEC_H264_NO_RC,
+       IMG_CODEC_H264_VBR,
+       IMG_CODEC_H264_CBR,
+       IMG_CODEC_H263_NO_RC,
+       IMG_CODEC_H263_VBR,
+       IMG_CODEC_H263_CBR,
+       IMG_CODEC_MPEG4_NO_RC,
+       IMG_CODEC_MPEG4_VBR,
+       IMG_CODEC_MPEG4_CBR,
+       IMG_CODEC_H264_VCM,
+       IMG_CODEC_NUM
+};
+
+
+typedef enum {
+       MTX_WRITEBACK_CMDWORD = 0,  //!< Command word of command executed by MTX
+       MTX_WRITEBACK_VALUE = 1,        //!< Writeback value returned by command
+       MTX_WRITEBACK_FLAGSWORD_0 = 2,  //!< Flags word indicating MTX status (see MTX writeback flags)
+       MTX_WRITEBACK_BITSWRITTEN = 3,  //!< number of bits written out by this core
+
+       MTX_WRITEBACK_DATASIZE      //!< End marker for enum
+
+} MTX_eWriteBackData;
+
+/* pnw_topazinit.c */
+int pnw_topaz_reset(struct drm_psb_private *dev_priv);
+int pnw_topaz_init_fw(struct drm_device *dev);
+int pnw_topaz_setup_fw(struct drm_device *dev, enum drm_pnw_topaz_codec codec);
+int pnw_topaz_wait_for_register(struct drm_psb_private *dev_priv,
+                               uint32_t addr, uint32_t value,
+                               uint32_t enable);
+/*void topaz_write_mtx_mem(struct drm_psb_private *dev_priv,
+                        uint32_t byte_addr, uint32_t val);
+uint32_t topaz_read_mtx_mem(struct drm_psb_private *dev_priv,
+                           uint32_t byte_addr);
+void topaz_write_mtx_mem_multiple_setup(struct drm_psb_private *dev_priv,
+                                       uint32_t addr);
+void topaz_write_mtx_mem_multiple(struct drm_psb_private *dev_priv,
+                                 uint32_t val);*/
+void pnw_topaz_mmu_flushcache(struct drm_psb_private *dev_priv);
+
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver);
+int pnw_video_get_core_num(struct drm_device *dev, uint64_t user_pointer);
+int pnw_topaz_kick_null_cmd(struct drm_psb_private *dev_priv,
+                           uint32_t core_id,
+                           uint32_t wb_offset,
+                           uint32_t sync_req,
+                           uint8_t irq_enable);
+int pnw_wait_on_sync(struct drm_psb_private *dev_priv,
+                    uint32_t sync_seq,
+                    uint32_t *sync_p);
+
+int pnw_video_frameskip(struct drm_device *dev, uint64_t user_pointer);
+
+static inline char *cmd_to_string(int cmd_id)
+{
+       switch (cmd_id) {
+       case MTX_CMDID_START_PIC:
+               return "MTX_CMDID_START_PIC";
+       case MTX_CMDID_END_PIC:
+               return "MTX_CMDID_END_PIC";
+       case MTX_CMDID_DO_HEADER:
+               return "MTX_CMDID_DO_HEADER";
+       case MTX_CMDID_ENCODE_SLICE:
+               return "MTX_CMDID_ENCODE_SLICE";
+       case MTX_CMDID_SW_NEW_CODEC:
+               return "MTX_CMDID_SW_NEW_CODEC";
+       case MTX_CMDID_SETQUANT:
+               return "MTX_CMDID_SETQUANT";
+       case MTX_CMDID_RESET_ENCODE:
+               return "MTX_CMDID_RESET_ENCODE";
+       case MTX_CMDID_ISSUEBUFF:
+               return "MTX_CMDID_ISSUEBUFF";
+       case MTX_CMDID_SETUP:
+               return "MTX_CMDID_SETUP";
+       case MTX_CMDID_SW_WRITEREG:
+               return "MTX_CMDID_SW_WRITEREG";
+       default:
+               return "Undefined command";
+
+       }
+}
+
+static inline char *codec_to_string(int codec)
+{
+       switch (codec) {
+       case IMG_CODEC_JPEG: /* Just guess, is JPEG firmware included in topaz_bin? */
+               return "JPEG";
+       case IMG_CODEC_H264_NO_RC:
+               return "H264_NO_RC";
+       case IMG_CODEC_H264_VBR:
+               return "H264_VBR";
+       case IMG_CODEC_H264_CBR:
+               return "H264_CBR";
+       case IMG_CODEC_H263_NO_RC:
+               return "H263_NO_RC";
+       case IMG_CODEC_H263_VBR:
+               return "H263_VBR";
+       case IMG_CODEC_H263_CBR:
+               return "H263_CBR";
+       case IMG_CODEC_MPEG4_NO_RC:
+               return "MPEG4_NO_RC";
+       case IMG_CODEC_MPEG4_VBR:
+               return "MPEG4_VBR";
+       case IMG_CODEC_MPEG4_CBR:
+               return "MPEG4_CBR";
+       case IMG_CODEC_H264_VCM:
+               return "H264_VCM";
+       default:
+               return "Undefined codec";
+       }
+}
+
+static inline void pnw_topaz_clearirq(struct drm_device *dev,
+                                     uint32_t clear_topaz)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       PSB_DEBUG_GENERAL("TOPAZ: clear IRQ\n");
+       if (clear_topaz != 0)
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR, clear_topaz, 0);
+
+       /* PSB_WVDC32(_PNW_IRQ_TOPAZ_FLAG, PSB_INT_IDENTITY_R); */
+}
+
+static inline uint32_t pnw_topaz_queryirq(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t val, /* iir, */ clear = 0;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       TOPAZ_READ32(TOPAZ_CR_IMG_TOPAZ_INTSTAT, &val, 0);
+       /* iir = PSB_RVDC32(PSB_INT_IDENTITY_R); */
+
+       (void) topaz_priv;
+
+       if ((val == 0) /* && (iir == 0) */) {/* no interrupt */
+               PSB_DEBUG_GENERAL("TOPAZ: no interrupt,IIR=TOPAZ_INTSTAT=0\n");
+               return 0;
+       }
+
+       PSB_DEBUG_IRQ("TOPAZ:TOPAZ_INTSTAT=0x%08x\n", val);
+
+       if (val & (1 << 31))
+               PSB_DEBUG_IRQ("TOPAZ:IRQ pin activated,cmd seq=0x%04x,"
+                             "sync seq: 0x%08x vs 0x%08x (MTX)\n",
+                             topaz_priv->aui32LastSync[0][0] ,
+                             dev_priv->sequence[LNC_ENGINE_ENCODE],
+                             *((uint32_t *)topaz_priv->topaz_mtx_wb + MTX_WRITEBACK_VALUE));
+       else
+               PSB_DEBUG_IRQ("TOPAZ:IRQ pin not activated,cmd seq=0x%04x,"
+                             "sync seq: 0x%08x vs 0x%08x (MTX)\n",
+                             topaz_priv->aui32LastSync[0][0],
+                             dev_priv->sequence[LNC_ENGINE_ENCODE],
+                             *((uint32_t *)topaz_priv->topaz_mtx_wb + MTX_WRITEBACK_VALUE));
+
+       if (val & 0x8) {
+               uint32_t mmu_status, mmu_req;
+
+               TOPAZ_READ32(TOPAZ_CR_MMU_STATUS, &mmu_status, 0);
+               TOPAZ_READ32(TOPAZ_CR_MMU_MEM_REQ, &mmu_req, 0);
+
+               PSB_DEBUG_IRQ("TOPAZ: detect a page fault interrupt, "
+                             "address=0x%08x,mem req=0x%08x\n",
+                             mmu_status, mmu_req);
+               clear |= F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MMU_FAULT);
+       }
+
+       if (val & 0x4) {
+               PSB_DEBUG_IRQ("TOPAZ: detect a MTX_HALT interrupt\n");
+               clear |= F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX_HALT);
+       }
+
+       if (val & 0x2) {
+               PSB_DEBUG_IRQ("TOPAZ: detect a MTX interrupt\n");
+               clear |= F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX);
+       }
+
+       if (val & 0x1) {
+               PSB_DEBUG_IRQ("TOPAZ: detect a MVEA interrupt\n");
+               clear |= F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MVEA);
+       }
+
+       return clear;
+}
+
+/*Set whether the write operation take effect on all cores
+ * or only the specific one*/
+static inline void topaz_set_mtx_target(struct drm_psb_private *dev_priv,
+                                       uint32_t core, uint8_t bTargetAll)
+{
+       TOPAZ_MULTICORE_WRITE32(
+               TOPAZSC_CR_MULTICORE_CORE_SEL_0,
+               F_ENCODE((bTargetAll), TOPAZSC_CR_WRITES_CORE_ALL) |
+               F_ENCODE(core, TOPAZSC_CR_DMAC_CORE_SELECT));
+
+}
+
+#endif /* _PNW_TOPAZ_H_ */
diff --git a/drivers/staging/mrst/imgv/pnw_topazinit.c b/drivers/staging/mrst/imgv/pnw_topazinit.c
new file mode 100644 (file)
index 0000000..c4f2555
--- /dev/null
@@ -0,0 +1,2095 @@
+/**
+ * file pnw_topazinit.c
+ * TOPAZ initialization and mtx-firmware upload
+ *
+ */
+
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+/* NOTE: (READ BEFORE REFINE CODE)
+ * 1. The FIRMWARE's SIZE is measured by byte, we have to pass the size
+ * measured by word to DMAC.
+ *
+ *
+ *
+ */
+
+/* include headers */
+
+/* #define DRM_DEBUG_CODE 2 */
+
+#include <linux/firmware.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "psb_drv.h"
+#include "pnw_topaz.h"
+#include "psb_powermgmt.h"
+#include "pnw_topaz_hw_reg.h"
+
+/* WARNING: this define is very important */
+#define RAM_SIZE (1024 * 24)
+
+#define        MEMORY_ONLY 0
+#define        MEM_AND_CACHE 1
+#define CACHE_ONLY 2
+
+#define FIRMWARE_NAME "topazsc_fw.bin"
+#define TOPAZ_KICK_RETRY_MAX 5
+
+/* static function define */
+static int topaz_upload_fw(struct drm_device *dev,
+                          enum drm_pnw_topaz_codec codec,
+                          uint32_t core_id);
+
+#define UPLOAD_FW_BY_DMA 1
+
+#if UPLOAD_FW_BY_DMA
+static int topaz_dma_transfer(struct drm_psb_private *dev_priv,
+                             uint32_t channel, uint32_t src_phy_addr,
+                             uint32_t offset, uint32_t dst_addr,
+                             uint32_t byte_num, uint32_t is_increment,
+                             uint32_t is_write);
+#else
+static void topaz_mtx_upload_by_register(struct drm_device *dev,
+               uint32_t mtx_mem, uint32_t addr,
+               uint32_t size,
+               struct ttm_buffer_object *buf,
+               uint32_t core);
+#endif
+
+static void get_mtx_control_from_dash(struct drm_psb_private *dev_priv,
+                                     uint32_t core);
+static void release_mtx_control_from_dash(struct drm_psb_private *dev_priv,
+               uint32_t core);
+static void pnw_topaz_mmu_hwsetup(struct drm_psb_private *dev_priv,
+                                 uint32_t core_id);
+static int  mtx_dma_read(struct drm_device *dev, uint32_t core,
+                        uint32_t source_addr, uint32_t size);
+static int  mtx_dma_write(struct drm_device *dev,
+                         uint32_t core);
+
+/* Reset the encode system buffer registers.*/
+static int pnw_topazsc_reset_ESB(struct drm_psb_private *dev_priv, int core_id)
+{
+       int x_pos, y_pos, i;
+
+       MVEA_WRITE32(MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP(ESB_HWSYNC),
+                    MVEASETUPESBREGION(0, 0,
+                                       TOPAZSC_ESB_REGION_HEIGH,
+                                       TOPAZSC_ESB_REGION_WIDTH,
+                                       TOPAZSC_ESB_REGION_HEIGH,
+                                       REGION_TYPE_LINEAR),
+                    core_id);
+       MVEA_WRITE32(MVEA_CR_CMC_PROC_ESB_ACCESS, ESB_HWSYNC, core_id);
+
+       i = 0;
+       for (y_pos = 0; y_pos < TOPAZSC_ESB_REGION_Y_MAX; y_pos++) {
+               for (x_pos = 0; x_pos < TOPAZSC_ESB_REGION_X_MAX;
+                    x_pos += 4, i += 4) {
+                       MVEA_ESB_WRITE32(i, 0, core_id);
+               }
+       }
+
+       MVEA_WRITE32(MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP(ESB_HWSYNC),
+                    MVEASETUPESBREGION(0, TOPAZSC_ESB_REGION_WIDTH,
+                                       TOPAZSC_ESB_REGION_HEIGH,
+                                       TOPAZSC_ESB_REGION_WIDTH,
+                                       TOPAZSC_ESB_REGION_HEIGH,
+                                       REGION_TYPE_LINEAR),
+                    core_id);
+
+       i = 0;
+       for (y_pos = 0; y_pos < TOPAZSC_ESB_REGION_Y_MAX; y_pos++) {
+               for (x_pos = 0; x_pos < TOPAZSC_ESB_REGION_X_MAX;
+                    x_pos += 4, i += 4) {
+                       MVEA_ESB_WRITE32(i, 0, core_id);
+               }
+       }
+
+       MVEA_WRITE32(MVEA_CR_CMC_PROC_ESB_ACCESS, 0, core_id);
+       return 0;
+}
+
+static int pnw_error_dump_reg(struct drm_psb_private *dev_priv, int core_id)
+{
+       uint32_t reg_val;
+       int i;
+       DRM_ERROR("DMA Register value dump:\n");
+       for (i = 0; i < 8; i++) {
+               DMAC_READ32(i * 4, &reg_val);
+               DRM_ERROR("DMAC REG%d: 0x%08x\n", i, reg_val);
+       }
+       TOPAZ_MULTICORE_READ32(
+               TOPAZSC_CR_MULTICORE_CORE_SEL_0, &reg_val);
+       DRM_ERROR("TOPAZSC_CR_MULTICORE_CORE_SEL_0 0x%08x\n", reg_val);
+       MTX_READ32(MTX_CR_MTX_SYSC_CDMAA, &reg_val, core_id);
+       DRM_ERROR("MTX_CR_MTX_SYSC_CDMAA 0x%08x\n", reg_val);
+       MTX_READ32(MTX_CR_MTX_SYSC_CDMAC, &reg_val, core_id);
+       DRM_ERROR("MTX_CR_MTX_SYSC_CDMAC 0x%08x\n", reg_val);
+
+       MTX_READ32(MTX_CR_MTX_SYSC_CDMAS0 , &reg_val, core_id);
+       DRM_ERROR("MTX_CR_MTX_SYSC_CDMAS0 0x%08x\n", reg_val);
+       MTX_READ32(MTX_CR_MTX_SYSC_CDMAS1, &reg_val, core_id);
+       DRM_ERROR("MTX_CR_MTX_SYSC_CDMAS1 0x%08x\n", reg_val);
+       MTX_READ32(MTX_CR_MTX_SYSC_CDMAT, &reg_val, core_id);
+       DRM_ERROR("MTX_CR_MTX_SYSC_CDMAT 0x%08x\n", reg_val);
+       for (i = 0; i < 6; i++) {
+               TOPAZ_READ32(0x1c + i * 4, &reg_val, core_id);
+               DRM_ERROR("MMU REG %d value 0x%08x\n", i, reg_val);
+       }
+
+       topaz_read_core_reg(dev_priv, core_id, TOPAZ_MTX_PC, &reg_val);
+       DRM_ERROR("PC pointer: 0x%08x\n", reg_val);
+
+       TOPAZ_MULTICORE_READ32(TOPAZSC_CR_MULTICORE_CMD_FIFO_1,
+                       &reg_val);
+       reg_val &= MASK_TOPAZSC_CR_CMD_FIFO_SPACE;
+       DRM_ERROR("TOPAZSC: Free words in command FIFO %d\n", reg_val);
+
+       return 0;
+}
+
+int pnw_topaz_wait_for_register(struct drm_psb_private *dev_priv,
+                               uint32_t addr, uint32_t value, uint32_t mask)
+{
+       uint32_t tmp;
+       uint32_t count = 1000000;
+
+       /* # poll topaz register for certain times */
+       while (count) {
+               /* #.# read */
+               MM_READ32(addr, 0, &tmp);
+
+               if (value == (tmp & mask))
+                       return 0;
+
+               /* #.# delay and loop */
+               PSB_UDELAY(1);
+               --count;
+       }
+
+       /* # now waiting is timeout, return 1 indicat failed */
+       /* XXX: testsuit means a timeout 10000 */
+
+       DRM_ERROR("TOPAZ:time out to poll addr(0x%x) expected value(0x%08x), "
+                 "actual 0x%08x (0x%08x & 0x%08x)\n",
+                 addr, value, tmp & mask, tmp, mask);
+
+       return -EBUSY;
+
+}
+
+static ssize_t psb_topaz_pmstate_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
+       struct drm_psb_private *dev_priv;
+       struct pnw_topaz_private *topaz_priv;
+       unsigned int pmstate;
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (drm_dev == NULL)
+               return 0;
+
+       dev_priv = drm_dev->dev_private;
+       topaz_priv = dev_priv->topaz_private;
+       pmstate = topaz_priv->pmstate;
+
+       pmstate = topaz_priv->pmstate;
+       spin_lock_irqsave(&topaz_priv->topaz_lock, flags);
+       ret = snprintf(buf, 64, "%s\n",
+                      (pmstate == PSB_PMSTATE_POWERUP) ?
+                      "powerup" : "powerdown");
+       spin_unlock_irqrestore(&topaz_priv->topaz_lock, flags);
+
+       return ret;
+}
+
+static DEVICE_ATTR(topaz_pmstate, 0444, psb_topaz_pmstate_show, NULL);
+
+
+/* this function finish the first part of initialization, the rest
+ * should be done in pnw_topaz_setup_fw
+ */
+int pnw_topaz_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct ttm_bo_device *bdev = &dev_priv->bdev;
+       uint32_t core_id, core_rev;
+       int ret = 0, n;
+       bool is_iomem;
+       struct pnw_topaz_private *topaz_priv;
+       void *topaz_bo_virt;
+
+       PSB_DEBUG_GENERAL("TOPAZ: init topazsc data structures\n");
+       topaz_priv = kmalloc(sizeof(struct pnw_topaz_private), GFP_KERNEL);
+       if (topaz_priv == NULL)
+               return -1;
+
+       dev_priv->topaz_private = topaz_priv;
+       memset(topaz_priv, 0, sizeof(struct pnw_topaz_private));
+
+       /* get device --> drm_device --> drm_psb_private --> topaz_priv
+        * for psb_topaz_pmstate_show: topaz_pmpolicy
+        * if not pci_set_drvdata, can't get drm_device from device
+        */
+       pci_set_drvdata(dev->pdev, dev);
+       if (device_create_file(&dev->pdev->dev,
+                              &dev_attr_topaz_pmstate))
+               DRM_ERROR("TOPAZ: could not create sysfs file\n");
+       topaz_priv->sysfs_pmstate = sysfs_get_dirent(dev->pdev->dev.kobj.sd,
+                                               NULL, "topaz_pmstate");
+
+       topaz_priv = dev_priv->topaz_private;
+
+       /* # initialize comand topaz queueing [msvdx_queue] */
+       INIT_LIST_HEAD(&topaz_priv->topaz_queue);
+       /* # init mutex? CHECK: mutex usage [msvdx_mutex] */
+       mutex_init(&topaz_priv->topaz_mutex);
+       /* # spin lock init? CHECK spin lock usage [msvdx_lock] */
+       spin_lock_init(&topaz_priv->topaz_lock);
+
+       /* # topaz status init. [msvdx_busy] */
+       topaz_priv->topaz_busy = 0;
+       /*Initial topaz_cmd_count should be larger than initial
+        *writeback value*/
+       topaz_priv->topaz_cmd_count = 1;
+       topaz_priv->topaz_fw_loaded = 0;
+       /* FIXME: workaround since JPEG firmware is not ready */
+       topaz_priv->topaz_cur_codec = 0;
+       topaz_priv->topaz_hw_busy = 1;
+       /* # gain write back structure,we may only need 32+4=40DW */
+       ret = ttm_buffer_object_create(bdev, 4096,
+                                      ttm_bo_type_kernel,
+                                      DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+                                      0, 0, 0, NULL, &(topaz_priv->topaz_bo));
+       if (ret != 0) {
+               DRM_ERROR("TOPAZ: failed to allocate topaz BO.\n");
+               return -1;
+       }
+
+       ret = ttm_bo_kmap(topaz_priv->topaz_bo, 0,
+                         topaz_priv->topaz_bo->num_pages,
+                         &topaz_priv->topaz_bo_kmap);
+       if (ret) {
+               DRM_ERROR("TOPAZ: map topaz BO bo failed......\n");
+               ttm_bo_unref(&topaz_priv->topaz_bo);
+               return -1;
+       }
+
+       TOPAZ_READ32(TOPAZ_CR_TOPAZ_HW_CFG, &topaz_priv->topaz_num_cores, 0);
+
+       topaz_priv->topaz_num_cores = F_EXTRACT(topaz_priv->topaz_num_cores,
+                                               TOPAZ_CR_NUM_CORES_SUPPORTED);
+       PSB_DEBUG_GENERAL("TOPAZ: number of cores: %d\n",
+                         topaz_priv->topaz_num_cores);
+
+       if (topaz_priv->topaz_num_cores > TOPAZSC_NUM_CORES) {
+               topaz_priv->topaz_num_cores = TOPAZSC_NUM_CORES;
+               DRM_ERROR("TOPAZ: number of cores (%d) exceed "
+                         "TOPAZSC_NUM_CORES (%d)!\n",
+                         topaz_priv->topaz_num_cores, TOPAZSC_NUM_CORES);
+       }
+
+       for (n = 0; n <  MAX_TOPAZ_CORES; n++) {
+               topaz_priv->topaz_mtx_data_mem[n] = NULL;
+               topaz_priv->topaz_mtx_reg_state[n] = NULL;
+               topaz_priv->cur_mtx_data_size[n] = 0;
+               topaz_priv->topaz_fw[n].text = NULL;
+               topaz_priv->topaz_fw[n].data = NULL;
+       }
+
+       for (n = 0; n < topaz_priv->topaz_num_cores; n++) {
+               TOPAZ_READ32(TOPAZ_CR_IMG_TOPAZ_CORE_ID, &core_id, n);
+               TOPAZ_READ32(TOPAZ_CR_IMG_TOPAZ_CORE_REV, &core_rev, n);
+
+               PSB_DEBUG_GENERAL("TOPAZ: core(%d), core_id(%x) core_rev(%x)\n",
+                                 n, core_id, core_rev);
+
+               topaz_priv->topaz_mtx_reg_state[n] = kmalloc(TOPAZ_MTX_REG_SIZE,
+                                                    GFP_KERNEL);
+               if (topaz_priv->topaz_mtx_reg_state[n] == NULL) {
+                       DRM_ERROR("TOPAZ: failed to allocate space "
+                                 "for mtx register\n");
+                       goto out;
+               }
+
+               ret = ttm_buffer_object_create(bdev,
+                                              12 * 4096,
+                                              ttm_bo_type_kernel,
+                                              DRM_PSB_FLAG_MEM_MMU |
+                                              TTM_PL_FLAG_NO_EVICT,
+                                              0, 0, 0, NULL,
+                                              &topaz_priv->topaz_mtx_data_mem[n]);
+               if (ret) {
+                       DRM_ERROR("TOPAZ: failed to allocate ttm buffer for "
+                                 "mtx data save of core (%d)\n", n);
+                       goto out;
+               }
+
+       }
+
+       topaz_bo_virt = ttm_kmap_obj_virtual(&topaz_priv->topaz_bo_kmap,
+                                            &is_iomem);
+       topaz_priv->topaz_mtx_wb = (uint32_t *) topaz_bo_virt;
+       topaz_priv->topaz_wb_offset = topaz_priv->topaz_bo->offset;
+       topaz_priv->topaz_sync_addr = (uint32_t *)(topaz_bo_virt
+                                     + 2048);
+       topaz_priv->topaz_sync_offset = topaz_priv->topaz_wb_offset
+                                       + 2048;
+
+       PSB_DEBUG_GENERAL("TOPAZ: alloc BO for WriteBack\n");
+       PSB_DEBUG_GENERAL("TOPAZ: WB offset=0x%08x\n",
+                         topaz_priv->topaz_wb_offset);
+       PSB_DEBUG_GENERAL("TOPAZ: SYNC offset=0x%08x\n",
+                         topaz_priv->topaz_sync_offset);
+
+       /*topaz_cmd_count starts with 1. Reset writback value with 0*/
+       memset((void *)(topaz_priv->topaz_mtx_wb), 0,
+              topaz_priv->topaz_num_cores
+              * MTX_WRITEBACK_DATASIZE_ROUND);
+       memset((void *)topaz_priv->topaz_sync_addr, 0,
+              MTX_WRITEBACK_DATASIZE_ROUND);
+
+       /*fence sequence number starts with 0. Reset sync seq with ~1*/
+       *(topaz_priv->topaz_sync_addr) = ~0;
+
+       pnw_topaz_mmu_flushcache(dev_priv);
+
+       /* # set up MMU */
+       for (n = 0; n < topaz_priv->topaz_num_cores; n++)
+               pnw_topaz_mmu_hwsetup(dev_priv, n);
+
+
+       for (n = 0; n < topaz_priv->topaz_num_cores; n++) {
+               /* # reset topaz */
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                            |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                            n);
+
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                            |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                            n);
+       }
+
+       PSB_DEBUG_GENERAL("TOPAZ: Reset MVEA successfully.\n");
+
+       for (n = 0; n < MAX_TOPAZ_CORES + 1; n++) {
+               topaz_priv->aui32LastSync[0][n] = ~0;
+               topaz_priv->aui32LastSync[1][n] = ~0;
+       }
+
+       /* create firmware storage */
+       for (n = 0; n < IMG_CODEC_NUM * 2; ++n) {
+               /* #.# malloc DRM object for fw storage */
+               ret = ttm_buffer_object_create(bdev, 12 * 4096,
+                                              ttm_bo_type_kernel,
+                                              DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+                                              0, 0, 0, NULL, &topaz_priv->topaz_fw[n].text);
+               if (ret) {
+                       DRM_ERROR("Failed to allocate firmware.\n");
+                       goto out;
+               }
+
+               /* #.# malloc DRM object for fw storage */
+               ret = ttm_buffer_object_create(bdev, 12 * 4096,
+                                              ttm_bo_type_kernel,
+                                              DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+                                              0, 0, 0, NULL, &topaz_priv->topaz_fw[n].data);
+               if (ret) {
+                       DRM_ERROR("Failed to allocate firmware.\n");
+                       goto out;
+               }
+       }
+
+       PSB_DEBUG_INIT("TOPAZ:old clock gating disable = 0x%08x\n",
+                      PSB_RVDC32(PSB_TOPAZ_CLOCKGATING));
+
+       PSB_DEBUG_INIT("TOPAZ:reset to disable clock gating\n");
+
+       PSB_WVDC32(0x007fffff, PSB_TOPAZ_CLOCKGATING);
+
+       PSB_DEBUG_GENERAL("TOPAZ: Exit initialization\n");
+       return 0;
+
+out:
+       for (n = 0; n < IMG_CODEC_NUM * 2; ++n) {
+               if (topaz_priv->topaz_fw[n].text != NULL)
+                       ttm_bo_unref(&topaz_priv->topaz_fw[n].text);
+               if (topaz_priv->topaz_fw[n].data != NULL)
+                       ttm_bo_unref(&topaz_priv->topaz_fw[n].data);
+       }
+
+       for (n = 0; n < MAX_TOPAZ_CORES; n++) {
+               if (topaz_priv->topaz_mtx_data_mem[n] != NULL)
+                       ttm_bo_unref(&topaz_priv->topaz_mtx_data_mem[n]);
+               if (topaz_priv->topaz_mtx_reg_state[n] != NULL)
+                       kfree(topaz_priv->topaz_mtx_reg_state[n]);
+       }
+
+       return ret;
+}
+
+int pnw_topaz_uninit(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       int n;
+
+       /* flush MMU */
+       PSB_DEBUG_GENERAL("XXX: need to flush mmu cache here??\n");
+       /* pnw_topaz_mmu_flushcache (dev_priv); */
+
+       if (NULL == topaz_priv) {
+               DRM_ERROR("TOPAZ: topaz_priv is NULL!\n");
+               return -1;
+       }
+
+       /* # reset TOPAZ chip */
+       pnw_topaz_reset(dev_priv);
+
+       /* release resources */
+       /* # release write back memory */
+       topaz_priv->topaz_mtx_wb = NULL;
+
+       for (n = 0; n < topaz_priv->topaz_num_cores; n++) {
+               /* release mtx register save space */
+               kfree(topaz_priv->topaz_mtx_reg_state[n]);
+
+               /* release mtx data memory save space */
+               if (topaz_priv->topaz_mtx_data_mem[n])
+                       ttm_bo_unref(&topaz_priv->topaz_mtx_data_mem[n]);
+       }
+       /* # release firmware storage */
+       for (n = 0; n < IMG_CODEC_NUM * 2; ++n) {
+               if (topaz_priv->topaz_fw[n].text != NULL)
+                       ttm_bo_unref(&topaz_priv->topaz_fw[n].text);
+               if (topaz_priv->topaz_fw[n].data != NULL)
+                       ttm_bo_unref(&topaz_priv->topaz_fw[n].data);
+       }
+
+       ttm_bo_kunmap(&topaz_priv->topaz_bo_kmap);
+       ttm_bo_unref(&topaz_priv->topaz_bo);
+
+       if (topaz_priv) {
+               pci_set_drvdata(dev->pdev, NULL);
+               device_remove_file(&dev->pdev->dev, &dev_attr_topaz_pmstate);
+               sysfs_put(topaz_priv->sysfs_pmstate);
+               topaz_priv->sysfs_pmstate = NULL;
+
+               kfree(topaz_priv);
+               dev_priv->topaz_private = NULL;
+       }
+
+       return 0;
+}
+
+int pnw_topaz_reset(struct drm_psb_private *dev_priv)
+{
+       struct pnw_topaz_private *topaz_priv;
+       uint32_t i;
+
+       topaz_priv = dev_priv->topaz_private;
+       topaz_priv->topaz_busy = 0;
+       topaz_priv->topaz_cmd_count = 0;
+       for (i = 0; i < MAX_TOPAZ_CORES; i++)
+               topaz_priv->cur_mtx_data_size[i] = 0;
+       topaz_priv->topaz_needs_reset = 0;
+
+       memset((void *)(topaz_priv->topaz_mtx_wb), 0,
+              MAX_TOPAZ_CORES * MTX_WRITEBACK_DATASIZE_ROUND);
+
+       for (i = 0; i < topaz_priv->topaz_num_cores; i++) {
+               /* # reset topaz */
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                            |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                            i);
+
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                            |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                            i);
+       }
+
+       /* # set up MMU */
+       for (i = 0; i < topaz_priv->topaz_num_cores; i++)
+               pnw_topaz_mmu_hwsetup(dev_priv, i);
+
+       return 0;
+}
+
+
+/* read firmware bin file and load all data into driver */
+int pnw_topaz_init_fw(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       const struct firmware *raw = NULL;
+       unsigned char *ptr;
+       int ret = 0;
+       int n;
+       struct topazsc_fwinfo *cur_fw;
+       int cur_size, total_size;
+       struct pnw_topaz_codec_fw *cur_codec;
+       struct ttm_buffer_object **cur_drm_obj;
+       struct ttm_bo_kmap_obj tmp_kmap;
+       bool is_iomem;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       topaz_priv->stored_initial_qp = 0;
+
+       /* # get firmware */
+       ret = request_firmware(&raw, FIRMWARE_NAME, &dev->pdev->dev);
+       if (ret != 0) {
+               DRM_ERROR("TOPAZ: request_firmware failed: %d\n", ret);
+               return ret;
+       }
+
+       if ((NULL == raw) || (raw->size < sizeof(struct topazsc_fwinfo))) {
+               DRM_ERROR("TOPAZ: firmware file is not correct size.\n");
+               goto out;
+       }
+
+       total_size = raw->size;
+       PSB_DEBUG_GENERAL("TOPAZ: opened firmware, size %d\n", raw->size);
+
+       ptr = (unsigned char *) raw->data;
+
+       if (!ptr) {
+               DRM_ERROR("TOPAZ: failed to load firmware.\n");
+               goto out;
+       }
+
+       /* # load fw from file */
+       PSB_DEBUG_GENERAL("TOPAZ: load firmware.....\n");
+       cur_fw = NULL;
+       for (n = 0; n < IMG_CODEC_NUM * 2; ++n) {
+               if (total_size < sizeof(struct topazsc_fwinfo)) {
+                       PSB_DEBUG_GENERAL("TOPAZ: WARNING: Rearch end of "
+                                         "firmware. Have loaded %d firmwares.",
+                                         n);
+                       break;
+               }
+
+               total_size -=  sizeof(struct topazsc_fwinfo);
+               cur_fw = (struct topazsc_fwinfo *) ptr;
+
+               cur_codec = &topaz_priv->topaz_fw[cur_fw->codec];
+               cur_codec->ver = cur_fw->ver;
+               cur_codec->codec = cur_fw->codec;
+               cur_codec->text_size = cur_fw->text_size;
+               cur_codec->data_size = cur_fw->data_size;
+               cur_codec->data_location = cur_fw->data_location;
+
+               total_size -= cur_fw->text_size;
+               total_size -= cur_fw->data_size;
+
+               if (total_size < 0) {
+                       PSB_DEBUG_GENERAL("TOPAZ: WARNING: wrong size number "
+                                         "of data or text. Have loaded"
+                                         " %d firmwares.", n);
+                       break;
+               }
+
+               PSB_DEBUG_GENERAL("TOPAZ: load firemware %s.\n",
+                                 codec_to_string(cur_fw->codec / 2));
+
+               /* #.# handle text section */
+               ptr += sizeof(struct topazsc_fwinfo);
+               cur_drm_obj = &cur_codec->text;
+               cur_size = cur_fw->text_size;
+
+               /* #.# fill DRM object with firmware data */
+               ret = ttm_bo_kmap(*cur_drm_obj, 0, (*cur_drm_obj)->num_pages,
+                                 &tmp_kmap);
+               if (ret) {
+                       PSB_DEBUG_GENERAL("drm_bo_kmap failed: %d\n", ret);
+                       ttm_bo_unref(cur_drm_obj);
+                       *cur_drm_obj = NULL;
+                       goto out;
+               }
+
+               PSB_DEBUG_GENERAL(" load codec %d, text_size: %d, "
+                                 "data_size %d, data_location 08%x\n",
+                                 cur_codec->codec / 2, cur_codec->text_size,
+                                 cur_codec->data_size, cur_codec->data_location);
+               memcpy(ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem), ptr,
+                      cur_size);
+
+               ttm_bo_kunmap(&tmp_kmap);
+
+               /* #.# handle data section */
+               ptr += cur_fw->text_size;
+               cur_drm_obj = &cur_codec->data;
+               cur_size = cur_fw->data_size;
+
+               /* #.# fill DRM object with firmware data */
+               ret = ttm_bo_kmap(*cur_drm_obj, 0, (*cur_drm_obj)->num_pages,
+                                 &tmp_kmap);
+               if (ret) {
+                       PSB_DEBUG_GENERAL("drm_bo_kmap failed: %d\n", ret);
+                       ttm_bo_unref(cur_drm_obj);
+                       *cur_drm_obj = NULL;
+                       goto out;
+               }
+
+               memcpy(ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem), ptr,
+                      cur_size);
+
+               ttm_bo_kunmap(&tmp_kmap);
+
+               /* #.# update ptr */
+               ptr += cur_fw->data_size;
+       }
+
+       release_firmware(raw);
+       PSB_DEBUG_GENERAL("TOPAZ: return from firmware init\n");
+
+       return 0;
+
+out:
+       if (raw) {
+               PSB_DEBUG_GENERAL("release firmware....\n");
+               release_firmware(raw);
+       }
+
+       return -1;
+}
+
+/* setup fw when start a new context */
+int pnw_topaz_setup_fw(struct drm_device *dev, enum drm_pnw_topaz_codec codec)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t verify_pc;
+       int core_id;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       int i, ret = 0;
+
+       /*Reset TopazSC*/
+       PSB_DEBUG_GENERAL("TOPAZ: should reset topaz when context change\n");
+
+       if (topaz_priv->topaz_num_cores > MAX_TOPAZ_CORES) {
+               DRM_ERROR("TOPAZ: Invalid core nubmer %d\n",
+                         topaz_priv->topaz_num_cores);
+               return -1;
+       }
+
+       PSB_DEBUG_GENERAL("TOPAZ: Set up mmu for all %d cores\n",
+                         topaz_priv->topaz_num_cores);
+
+       for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++)
+               pnw_topaz_mmu_hwsetup(dev_priv, core_id);
+
+       /* # reset MVEA */
+       for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+               pnw_topazsc_reset_ESB(dev_priv, core_id);
+
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                            |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                            core_id);
+
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                            |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                            core_id);
+       }
+
+       psb_irq_uninstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
+
+       PSB_DEBUG_GENERAL("TOPAZ: will setup firmware ....\n");
+
+       /*start each MTX in turn MUST start with master to
+        * enable comms to other cores*/
+       for (core_id = topaz_priv->topaz_num_cores - 1;
+            core_id >= 0; core_id--) {
+               topaz_set_mtx_target(dev_priv, core_id, 0);
+               /* # reset mtx */
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+                             F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET)
+                             |
+                             F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET) |
+                             F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET),
+                             core_id);
+
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST, 0x0, core_id);
+
+               /* # upload fw by drm */
+               PSB_DEBUG_GENERAL("TOPAZ: will upload firmware to %d cores\n",
+                                 topaz_priv->topaz_num_cores);
+
+               topaz_upload_fw(dev, codec, core_id);
+
+               PSB_DEBUG_GENERAL("TOPAZ: after upload fw ....\n");
+
+               /* D0.5, D0.6 and D0.7 */
+               for (i = 5; i < 8; i++) {
+                       topaz_write_core_reg(dev_priv, core_id, 0x1 | (i << 4),
+                                            0);
+               }
+               /* Saves 8 Registers of D1 Bank  */
+               /* D1.5, D1.6 and D1.7 */
+               for (i = 5; i < 8; i++) {
+                       topaz_write_core_reg(dev_priv, core_id, 0x2 | (i << 4),
+                                            0);
+               }
+
+               PSB_DEBUG_GENERAL("TOPAZ: setting up pc address: 0x%08x"
+                                 "for core (%d)\n",
+                                 PC_START_ADDRESS, core_id);
+               topaz_write_core_reg(dev_priv, core_id,
+                                    TOPAZ_MTX_PC, PC_START_ADDRESS);
+
+               topaz_read_core_reg(dev_priv, core_id,
+                                   TOPAZ_MTX_PC, &verify_pc);
+
+               PSB_DEBUG_GENERAL("TOPAZ: verify pc address for core"
+                                 " (%d):0x%08x\n",
+                                 core_id, verify_pc);
+
+               /* enable auto clock is essential for this driver */
+               TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_AUTO_CLK_GATE,
+                             F_ENCODE(1, TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE) |
+                             F_ENCODE(1, TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE),
+                             core_id);
+               MVEA_WRITE32(MVEA_CR_MVEA_AUTO_CLOCK_GATING,
+                            F_ENCODE(1, MVEA_CR_MVEA_IPE_AUTO_CLK_GATE) |
+                            F_ENCODE(1, MVEA_CR_MVEA_SPE_AUTO_CLK_GATE) |
+                            F_ENCODE(1, MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE) |
+                            F_ENCODE(1, MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE),
+                            core_id);
+
+               /* flush the command FIFO - only has effect on master MTX */
+               if (core_id == 0)
+                       TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_CMD_FIFO_2,
+                                     F_ENCODE(1, TOPAZ_CR_CMD_FIFO_FLUSH),
+                                     0);
+
+               /* clear MTX interrupt */
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR,
+                             F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX),
+                             core_id);
+
+               /* put the number of cores in use in the scratch register
+                * so is is ready when the firmware wakes up. */
+               TOPAZ_WRITE32(0x100 + (2 << 2), 2, core_id);
+
+               /* # turn on MTX */
+               topaz_set_mtx_target(dev_priv, core_id, 0);
+               MTX_WRITE32(MTX_CORE_CR_MTX_ENABLE_OFFSET,
+                           MTX_CORE_CR_MTX_ENABLE_MTX_ENABLE_MASK,
+                           core_id);
+
+               topaz_set_mtx_target(dev_priv, core_id, 0);
+               MTX_WRITE32(MTX_CR_MTX_KICK, 1, core_id);
+       }
+
+       topaz_priv->topaz_cmd_count = 1;
+       /* # poll on the interrupt which the firmware will generate */
+       /*With DDKv186, interrupt would't be generated automatically after
+        * firmware set up*/
+       PSB_DEBUG_GENERAL("TOPAZ: send NULL command to test firmware\n");
+       for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+               pnw_topaz_kick_null_cmd(dev_priv, core_id,
+                                       topaz_priv->topaz_sync_offset,
+                                       topaz_priv->topaz_cmd_count++, 0);
+
+               ret = pnw_wait_on_sync(dev_priv,
+                                      topaz_priv->topaz_cmd_count - 1,
+                                      topaz_priv->topaz_sync_addr
+                                      + MTX_WRITEBACK_VALUE);
+               if (0 != ret) {
+                       DRM_ERROR("TOPAZ: Failed to upload firmware for codec"
+                                 " %d!\n",
+                                 codec);
+                       pnw_error_dump_reg(dev_priv, core_id);
+                       return -1;
+               }
+
+               *(topaz_priv->topaz_sync_addr + MTX_WRITEBACK_VALUE)
+               = 0xa5a5a5a5;
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR,
+                             F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX),
+                             core_id);
+       }
+
+
+       PSB_DEBUG_GENERAL("TOPAZ: after topaz mtx setup ....\n");
+
+       memset((void *)(topaz_priv->topaz_mtx_wb),
+              0,
+              topaz_priv->topaz_num_cores
+              * MTX_WRITEBACK_DATASIZE_ROUND);
+
+       PSB_DEBUG_GENERAL("TOPAZ: firmware uploaded.\n");
+
+       topaz_priv->topaz_busy = 0;
+
+       for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+               MVEA_WRITE32(MVEA_CR_BUFFER_SIDEBAND,
+                            F_ENCODE(CACHE_ONLY, MVEA_CR_ABOVE_PARAM_OUT_SBAND) |
+                            F_ENCODE(CACHE_ONLY, MVEA_CR_BELOW_PARAM_OUT_SBAND) |
+                            F_ENCODE(MEM_AND_CACHE, MVEA_CR_ABOVE_PIX_OUT_SBAND) |
+                            F_ENCODE(MEM_AND_CACHE, MVEA_CR_RECON_SBAND) |
+                            F_ENCODE(CACHE_ONLY, MVEA_CR_REF_SBAND) |
+                            F_ENCODE(CACHE_ONLY, MVEA_CR_ABOVE_PARAM_IN_SBAND) |
+                            F_ENCODE(CACHE_ONLY, MVEA_CR_BELOW_PARAM_IN_SBAND) |
+                            F_ENCODE(MEMORY_ONLY, MVEA_CR_CURR_PARAM_SBAND) |
+                            F_ENCODE(CACHE_ONLY, MVEA_CR_ABOVE_PIX_IN_SBAND) |
+                            F_ENCODE(MEMORY_ONLY, MVEA_CR_CURR_MB_SBAND),
+                            core_id);
+               MVEA_WRITE32(MVEA_CR_IPE_JITTER_FACTOR, 3 - 1, core_id);
+
+               /*setup the jitter, base it on image size (using the height)*/
+               if (topaz_priv->frame_h >= 720)
+                       MVEA_WRITE32(MVEA_CR_IPE_JITTER_FACTOR, 3 - 1, core_id);
+               else if (topaz_priv->frame_w >= 480)
+                       MVEA_WRITE32(MVEA_CR_IPE_JITTER_FACTOR, 2 - 1, core_id);
+               else
+                       MVEA_WRITE32(MVEA_CR_IPE_JITTER_FACTOR, 3 - 1, core_id);
+       }
+
+       psb_irq_preinstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
+       psb_irq_postinstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
+       pnw_topaz_enableirq(dev);
+
+       return 0;
+}
+
+#if UPLOAD_FW_BY_DMA
+static int topaz_upload_fw(struct drm_device *dev, enum drm_pnw_topaz_codec codec, uint32_t core_id)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       const struct pnw_topaz_codec_fw *cur_codec_fw;
+       uint32_t text_size, data_size;
+       uint32_t data_location;
+       uint32_t cur_mtx_data_size;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       int ret = 0;
+
+       if (codec >= IMG_CODEC_NUM) {
+               DRM_ERROR("TOPAZ: Invalid codec %d\n", codec);
+               return -1;
+       }
+
+       /* # MTX reset */
+       PSB_DEBUG_GENERAL("TOPAZ: mtx reset.\n");
+       MTX_WRITE32(MTX_CORE_CR_MTX_SOFT_RESET_OFFSET,
+                   MTX_CORE_CR_MTX_SOFT_RESET_MTX_RESET_MASK,
+                   core_id);
+
+       /* # upload the master and slave firmware by DMA */
+       if (core_id == 0)
+               cur_codec_fw = &topaz_priv->topaz_fw[codec*2];
+       else
+               cur_codec_fw = &topaz_priv->topaz_fw[codec*2 + 1];
+
+       PSB_DEBUG_GENERAL("Topaz:upload codec %s(%d) text sz=%d data sz=%d\n"
+                         "data location(0x%08x) to core(%d).\n",
+                         codec_to_string(codec), codec,
+                         cur_codec_fw->text_size, cur_codec_fw->data_size,
+                         cur_codec_fw->data_location, core_id);
+
+       /* # upload text. text_size is byte size*/
+       text_size = cur_codec_fw->text_size / 4;
+       /* adjust transfer sizes of text and data sections to match burst size*/
+       text_size = ((text_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+                    & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+       PSB_DEBUG_GENERAL("TOPAZ: text_size round up to %d\n", text_size);
+       /* setup the MTX to start recieving data:
+          use a register for the transfer which will point to the source
+          (MTX_CR_MTX_SYSC_CDMAT) */
+       /*MTX burst size (4 * 2 * 32bits = 32bytes) should match DMA burst
+         size (2 * 128bits = 32bytes) */
+       /* #.# fill the dst addr */
+
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA, MTX_DMA_MEMORY_BASE, core_id);
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+                   F_ENCODE(4, MTX_BURSTSIZE) |
+                   F_ENCODE(0, MTX_RNW) |
+                   F_ENCODE(1, MTX_ENABLE) |
+                   F_ENCODE(text_size, MTX_LENGTH), core_id);
+
+       /* #.# set DMAC access to host memory via BIF (deserted)*/
+       /* TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, core_id);*/
+
+       /* #.# transfer the codec */
+       if (0 != topaz_dma_transfer(dev_priv, 0, cur_codec_fw->text->offset, 0,
+                                   MTX_CR_MTX_SYSC_CDMAT,
+                                   text_size, core_id, 0)) {
+               pnw_error_dump_reg(dev_priv, core_id);
+               return -1;
+       }
+
+       /* #.# wait dma finish */
+       ret = pnw_topaz_wait_for_register(dev_priv,
+                                         DMAC_START + IMG_SOC_DMAC_IRQ_STAT(0),
+                                         F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+                                         F_ENCODE(1, IMG_SOC_TRANSFER_FIN));
+       if (ret != 0) {
+               pnw_error_dump_reg(dev_priv, core_id);
+               return -1;
+       }
+
+       /* #.# clear interrupt */
+       DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+
+       PSB_DEBUG_GENERAL("TOPAZ: firmware text upload complete.\n");
+
+       /* # return access to topaz core (deserted)*/
+       /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, core_id);*/
+
+       /* # upload data */
+       data_size = cur_codec_fw->data_size / 4;
+       data_size = ((data_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+                    & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+       data_location = cur_codec_fw->data_location;
+       data_location = data_location & (~(MTX_DMA_BURSTSIZE_BYTES - 1));
+
+       PSB_DEBUG_GENERAL("TOPAZ: data_size round up to %d\n"
+                         "data_location round up to 0x%08x\n",
+                         data_size, data_location);
+       /* #.# fill the dst addr */
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA,
+                   data_location, core_id);
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+                   F_ENCODE(4, MTX_BURSTSIZE) |
+                   F_ENCODE(0, MTX_RNW) |
+                   F_ENCODE(1, MTX_ENABLE) |
+                   F_ENCODE(data_size, MTX_LENGTH), core_id);
+       /* #.# set DMAC access to host memory via BIF(deserted) */
+       /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, core_id);*/
+
+       /* #.# transfer the codec */
+       if (0 != topaz_dma_transfer(dev_priv, 0, cur_codec_fw->data->offset, 0,
+                                   MTX_CR_MTX_SYSC_CDMAT, data_size, core_id, 0)) {
+               pnw_error_dump_reg(dev_priv, core_id);
+               return -1;
+       }
+
+       /* #.# wait dma finish */
+       ret = pnw_topaz_wait_for_register(dev_priv,
+                                         DMAC_START + IMG_SOC_DMAC_IRQ_STAT(0),
+                                         F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+                                         F_ENCODE(1, IMG_SOC_TRANSFER_FIN));
+       if (ret != 0) {
+               pnw_error_dump_reg(dev_priv, core_id);
+               return -1;
+       }
+       /* #.# clear interrupt */
+       DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+
+       pnw_topaz_mmu_flushcache(dev_priv);
+       PSB_DEBUG_GENERAL("TOPAZ: firmware data upload complete.\n");
+       /* # return access to topaz core(deserted) */
+       /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, core_id);*/
+
+       /* record this codec's mtx data size for
+        * context save & restore */
+       /* FIXME: since non-root sighting fixed by pre allocated,
+        * only need to correct the buffer size
+        */
+       cur_mtx_data_size = cur_codec_fw->data_size / 4;
+       if (topaz_priv->cur_mtx_data_size[core_id] != cur_mtx_data_size)
+               topaz_priv->cur_mtx_data_size[core_id] = cur_mtx_data_size;
+
+       return 0;
+}
+
+#else
+
+void topaz_mtx_upload_by_register(struct drm_device *dev, uint32_t mtx_mem,
+                                 uint32_t addr, uint32_t size,
+                                 struct ttm_buffer_object *buf,
+                                 uint32_t core)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t *buf_p;
+       uint32_t debug_reg, bank_size, bank_ram_size, bank_count;
+       uint32_t cur_ram_id, ram_addr , ram_id;
+       int map_ret, lp;
+       struct ttm_bo_kmap_obj bo_kmap;
+       bool is_iomem;
+       uint32_t cur_addr, ui32Size;
+
+       PSB_DEBUG_GENERAL("TOPAZ: mtx upload: mtx_mem(0x%08x) addr(0x%08x)"
+                         "size(%d)\n", mtx_mem, addr, size);
+
+       get_mtx_control_from_dash(dev_priv, core);
+
+       map_ret = ttm_bo_kmap(buf, 0, buf->num_pages, &bo_kmap);
+       if (map_ret) {
+               DRM_ERROR("TOPAZ: drm_bo_kmap failed: %d\n", map_ret);
+               return;
+       }
+       buf_p = (uint32_t *) ttm_kmap_obj_virtual(&bo_kmap, &is_iomem);
+
+
+       TOPAZ_READ32(TOPAZ_CORE_CR_MTX_DEBUG_OFFSET, &debug_reg, core);
+       debug_reg = 0x0a0a0600;
+       /*bank_size = (debug_reg & 0xf0000) >> 16;
+         bank_ram_size = 1 << (bank_size + 2);*/
+
+       /*Bank size 4096, BanK number 6, Totally ram size:24k*/
+       ui32Size = 0x1 << (F_EXTRACT(debug_reg,
+                                    TOPAZ_CR_MTX_LAST_RAM_BANK_SIZE) + 2);
+       /* all other banks */
+       bank_size = 0x1 << (F_EXTRACT(debug_reg,
+                                     TOPAZ_CR_MTX_RAM_BANK_SIZE) + 2);
+       /* total RAM size */
+       bank_ram_size = ui32Size + (bank_size *
+                                   (F_EXTRACT(debug_reg, TOPAZ_CR_MTX_RAM_BANKS) - 1));
+
+       bank_count = (debug_reg & 0xf00) >> 8;
+
+       PSB_DEBUG_GENERAL("TOPAZ: bank size %d, bank count %d, ram size %d\n",
+                         bank_size, bank_count, bank_ram_size);
+
+       pnw_topaz_wait_for_register(dev_priv,
+                                   REG_START_TOPAZ_MTX_HOST(core)
+                                   + MTX_CR_MTX_RAM_ACCESS_STATUS,
+                                   MASK_MTX_MTX_MTX_MCM_STAT,
+                                   MASK_MTX_MTX_MTX_MCM_STAT);
+
+       cur_ram_id = -1;
+       cur_addr = addr;
+       for (lp = 0; lp < size / 4; ++lp) {
+               ram_id = mtx_mem + (cur_addr / bank_size);
+
+               if (cur_ram_id != ram_id) {
+                       ram_addr = cur_addr >> 2;
+
+                       MTX_WRITE32(MTX_CR_MTX_RAM_ACCESS_CONTROL,
+                                   F_ENCODE(ram_id, MTX_MTX_MCMID) |
+                                   F_ENCODE(ram_addr, MTX_MTX_MCM_ADDR) |
+                                   F_ENCODE(1, MTX_MTX_MCMAI),
+                                   core);
+
+                       cur_ram_id = ram_id;
+               }
+               cur_addr += 4;
+
+               MTX_WRITE32(MTX_CR_MTX_RAM_ACCESS_DATA_TRANSFER,
+                           *(buf_p + lp), core);
+
+               pnw_topaz_wait_for_register(dev_priv,
+                                           MTX_CR_MTX_RAM_ACCESS_STATUS
+                                           + REG_START_TOPAZ_MTX_HOST(core),
+                                           MASK_MTX_MTX_MTX_MCM_STAT,
+                                           MASK_MTX_MTX_MTX_MCM_STAT);
+       }
+
+       release_mtx_control_from_dash(dev_priv, core);
+       ttm_bo_kunmap(&bo_kmap);
+
+       PSB_DEBUG_GENERAL("TOPAZ: register data upload done\n");
+       return;
+}
+
+int topaz_upload_fw(struct drm_device *dev, enum drm_pnw_topaz_codec codec,
+                   uint32_t core_id)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       const struct pnw_topaz_codec_fw *cur_codec_fw;
+       uint32_t text_size, data_size;
+       uint32_t data_location;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       /* # refer HLD document */
+       /* # MTX reset */
+       PSB_DEBUG_GENERAL("TOPAZ: mtx reset.\n");
+       MTX_WRITE32(MTX_CORE_CR_MTX_SOFT_RESET_OFFSET,
+                   MTX_CORE_CR_MTX_SOFT_RESET_MTX_RESET_MASK,
+                   core_id);
+
+       /* # upload the master and slave firmware by DMA */
+       if (core_id == 0)
+               cur_codec_fw = &topaz_priv->topaz_fw[codec * 2];
+       else
+               cur_codec_fw = &topaz_priv->topaz_fw[codec * 2 + 1];
+
+       PSB_DEBUG_GENERAL("Topaz:upload codec by MTX reg %s(%d)"
+                         " text sz=%d data sz=%d"
+                         " data location(%d) to core(%d).\n",
+                         codec_to_string(codec), codec,
+                         cur_codec_fw->text_size, cur_codec_fw->data_size,
+                         cur_codec_fw->data_location, core_id);
+
+       /* # upload text */
+       text_size = cur_codec_fw->text_size;
+
+       topaz_mtx_upload_by_register(dev, MTX_CORE_CODE_MEM,
+                                    0,
+                                    /*PC_START_ADDRESS - MTX_MEMORY_BASE,*/
+                                    text_size, cur_codec_fw->text, core_id);
+
+       /* # upload data */
+       data_size = cur_codec_fw->data_size;
+       data_location = cur_codec_fw->data_location;
+
+       topaz_mtx_upload_by_register(dev, MTX_CORE_DATA_MEM,
+                                    data_location - MTX_DMA_MEMORY_BASE, data_size,
+                                    cur_codec_fw->data, core_id);
+
+       return 0;
+}
+
+#endif /* UPLOAD_FW_BY_DMA */
+
+/* is_increment is always 0, so use it as core_id for workaround*/
+static int topaz_dma_transfer(struct drm_psb_private *dev_priv, uint32_t channel,
+                      uint32_t src_phy_addr, uint32_t offset,
+                      uint32_t soc_addr, uint32_t byte_num,
+                      uint32_t is_increment, uint32_t is_write)
+{
+       uint32_t dmac_count;
+       uint32_t irq_stat;
+       uint32_t count;
+
+       PSB_DEBUG_GENERAL("TOPAZ: using dma to transfer firmware\n");
+       /* # check that no transfer is currently in progress and no
+          interrupts are outstanding ?? (why care interrupt) */
+       DMAC_READ32(IMG_SOC_DMAC_COUNT(channel), &dmac_count);
+       if (0 != (dmac_count & (MASK_IMG_SOC_EN | MASK_IMG_SOC_LIST_EN))) {
+               DRM_ERROR("TOPAZ: there is tranfer in progress\n");
+               return -1;
+       }
+
+       /* assert(0==(dmac_count & (MASK_IMG_SOC_EN | MASK_IMG_SOC_LIST_EN)));*/
+
+       /* clear status of any previous interrupts */
+       DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(channel), 0);
+
+       /* check irq status */
+       DMAC_READ32(IMG_SOC_DMAC_IRQ_STAT(channel), &irq_stat);
+       /* assert(0 == irq_stat); */
+       if (0 != irq_stat)
+               DRM_ERROR("TOPAZ: there is hold up\n");
+
+       /*MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA, MTX_DMA_MEMORY_BASE, is_increment);
+         MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+         F_ENCODE(4, MTX_BURSTSIZE) |
+         F_ENCODE(0, MTX_RNW) |
+         F_ENCODE(1, MTX_ENABLE) |
+         F_ENCODE(byte_num, MTX_LENGTH), is_increment);*/
+
+       /* per hold - allow HW to sort itself out */
+       DMAC_WRITE32(IMG_SOC_DMAC_PER_HOLD(channel), 16);
+       /* clear previous interrupts */
+       DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(channel), 0);
+
+       DMAC_WRITE32(IMG_SOC_DMAC_SETUP(channel),
+                    (src_phy_addr + offset));
+       count = DMAC_VALUE_COUNT(DMAC_BSWAP_NO_SWAP, DMAC_PWIDTH_32_BIT,
+                                is_write, DMAC_PWIDTH_32_BIT, byte_num);
+       /* generate an interrupt at the end of transfer */
+       /* count |= MASK_IMG_SOC_TRANSFER_IEN; */
+       /*count |= F_ENCODE(is_write, IMG_SOC_DIR);*/
+       DMAC_WRITE32(IMG_SOC_DMAC_COUNT(channel), count);
+
+       /* Burst : 2 * 128 bits = 32 bytes*/
+       DMAC_WRITE32(IMG_SOC_DMAC_PERIPH(channel),
+                    DMAC_VALUE_PERIPH_PARAM(DMAC_ACC_DEL_0,
+                                            0, DMAC_BURST_2));
+
+       /* is_increment here is actually core_id*/
+       DMAC_WRITE32(IMG_SOC_DMAC_PERIPHERAL_ADDR(channel),
+                    MTX_CR_MTX_SYSC_CDMAT
+                    + REG_START_TOPAZ_MTX_HOST(is_increment));
+
+       /* Finally, rewrite the count register with
+        * the enable bit set to kick off the transfer
+        */
+       DMAC_WRITE32(IMG_SOC_DMAC_COUNT(channel), count | MASK_IMG_SOC_EN);
+
+       PSB_DEBUG_GENERAL("TOPAZ: dma transfer started.\n");
+
+       return 0;
+}
+
+void topaz_write_core_reg(struct drm_psb_private *dev_priv,
+                         uint32_t core,
+                         uint32_t reg,
+                         const uint32_t val)
+{
+       uint32_t tmp;
+       get_mtx_control_from_dash(dev_priv, core);
+
+       /* put data into MTX_RW_DATA */
+       MTX_WRITE32(MTX_CORE_CR_MTX_REGISTER_READ_WRITE_DATA_OFFSET, val, core);
+
+       /* request a write */
+       tmp = reg &
+             ~MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK;
+
+       MTX_WRITE32(MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET,
+                   tmp, core);
+
+       /* wait for operation finished */
+       pnw_topaz_wait_for_register(dev_priv,
+                                   REG_START_TOPAZ_MTX_HOST(core) +
+                                   MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET,
+                                   MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,
+                                   MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+
+       release_mtx_control_from_dash(dev_priv, core);
+}
+
+void topaz_read_core_reg(struct drm_psb_private *dev_priv,
+                        uint32_t core,
+                        uint32_t reg,
+                        uint32_t *ret_val)
+{
+       uint32_t tmp;
+
+       get_mtx_control_from_dash(dev_priv, core);
+
+       /* request a write */
+       tmp = (reg &
+              ~MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+
+       MTX_WRITE32(MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET,
+                   MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_MASK
+                   | tmp, core);
+
+       /* wait for operation finished */
+       pnw_topaz_wait_for_register(dev_priv,
+                                   REG_START_TOPAZ_MTX_HOST(core) +
+                                   MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET,
+                                   MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,
+                                   MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+
+       /* read  */
+       MTX_READ32(MTX_CORE_CR_MTX_REGISTER_READ_WRITE_DATA_OFFSET,
+                  ret_val, core);
+
+       release_mtx_control_from_dash(dev_priv, core);
+}
+
+static void get_mtx_control_from_dash(struct drm_psb_private *dev_priv, uint32_t core)
+{
+       int debug_reg_slave_val;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       int count = 0;
+
+       /* GetMTXControlFromDash */
+       TOPAZ_WRITE32(TOPAZ_CORE_CR_MTX_DEBUG_OFFSET,
+                     F_ENCODE(1, TOPAZ_CR_MTX_DBG_IS_SLAVE) |
+                     F_ENCODE(2, TOPAZ_CR_MTX_DBG_GPIO_OUT), core);
+       do {
+               TOPAZ_READ32(TOPAZ_CORE_CR_MTX_DEBUG_OFFSET,
+                            &debug_reg_slave_val, core);
+               count++;
+       } while (((debug_reg_slave_val & 0x18) != 0) && count < 50000);
+
+       if (count >= 50000)
+               PSB_DEBUG_GENERAL("TOPAZ: timeout in "
+                                 "get_mtx_control_from_dash\n");
+
+       /* save access control */
+       TOPAZ_READ32(MTX_CORE_CR_MTX_RAM_ACCESS_CONTROL_OFFSET,
+                    &topaz_priv->topaz_dash_access_ctrl, core);
+}
+
+static void release_mtx_control_from_dash(struct drm_psb_private *dev_priv,
+                                  uint32_t core)
+{
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       /* restore access control */
+       TOPAZ_WRITE32(MTX_CORE_CR_MTX_RAM_ACCESS_CONTROL_OFFSET,
+                     topaz_priv->topaz_dash_access_ctrl, core);
+
+       /* release bus */
+       TOPAZ_WRITE32(TOPAZ_CORE_CR_MTX_DEBUG_OFFSET,
+                     F_ENCODE(1, TOPAZ_CR_MTX_DBG_IS_SLAVE), core);
+}
+
+static void pnw_topaz_mmu_hwsetup(struct drm_psb_private *dev_priv, uint32_t core_id)
+{
+       uint32_t pd_addr = psb_get_default_pd_addr(dev_priv->mmu);
+
+       PSB_DEBUG_GENERAL("TOPAZ: core (%d) MMU set up.\n", core_id);
+
+       /* bypass all request while MMU is being configured */
+       TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0,
+                     F_ENCODE(1, TOPAZ_CR_MMU_BYPASS)
+                     | F_ENCODE(1, TOPAZ_CR_MMU_BYPASS_DMAC), core_id);
+
+       /* set MMU hardware at the page table directory */
+       PSB_DEBUG_GENERAL("TOPAZ: write PD phyaddr=0x%08x "
+                         "into MMU_DIR_LIST0/1\n", pd_addr);
+       /*There's two of these (0) and (1).. only 0 is currently used*/
+       TOPAZ_WRITE32(TOPAZ_CR_MMU_DIR_LIST_BASE(0), pd_addr, core_id);
+       /*TOPAZ_WRITE32(TOPAZ_CR_MMU_DIR_LIST_BASE(1), 0, core_id);*/
+
+       /* setup index register, all pointing to directory bank 0 */
+       TOPAZ_WRITE32(TOPAZ_CR_MMU_BANK_INDEX, 0, core_id);
+
+       /* now enable MMU access for all requestors */
+       TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0,
+                     F_ENCODE(0, TOPAZ_CR_MMU_BYPASS)
+                     | F_ENCODE(0, TOPAZ_CR_MMU_BYPASS_DMAC), core_id);
+}
+
+void pnw_topaz_mmu_flushcache(struct drm_psb_private *dev_priv)
+{
+       uint32_t mmu_control;
+
+       if (dev_priv->topaz_disabled)
+               return;
+
+       PSB_DEBUG_GENERAL("TOPAZ: pnw_topaz_mmu_flushcache\n");
+#if 0
+       PSB_DEBUG_GENERAL("XXX: Only one PTD/PTE cache"
+                         " so flush using the master core\n");
+#endif
+       /* XXX: disable interrupt */
+       TOPAZ_READ32(TOPAZ_CR_MMU_CONTROL0, &mmu_control, 0);
+       mmu_control |= F_ENCODE(1, TOPAZ_CR_MMU_INVALDC);
+       /*mmu_control |= F_ENCODE(1, TOPAZ_CR_MMU_FLUSH);*/
+
+#if 0
+       PSB_DEBUG_GENERAL("Set Invalid flag (this causes a flush with MMU\n"
+                         "still operating afterwards even if not cleared,\n"
+                         "but may want to replace with MMU_FLUSH?\n");
+#endif
+       TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0, mmu_control, 0);
+
+       /* clear it */
+       mmu_control &= (~F_ENCODE(1, TOPAZ_CR_MMU_INVALDC));
+       //mmu_control &= (~F_ENCODE(1, TOPAZ_CR_MMU_FLUSH));
+       TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0, mmu_control, 0);
+       psb_gl3_global_invalidation(dev_priv->dev);
+}
+
+
+static void pnw_topaz_retry_kick(struct drm_device *dev, int core_id)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       int i, j;
+
+       for (j = 0; j < TOPAZ_KICK_RETRY_MAX; j++) {
+               PSB_DEBUG_GENERAL("TOPAZ: Kick was missing. Try again.\n");
+               topaz_set_mtx_target(dev_priv, 0, 0);
+               MTX_WRITE32(MTX_CR_MTX_KICK, 1, 0);
+               i = 3000;
+               PSB_DEBUG_GENERAL("TOPAZ: Wait for the NULL command...\n");
+               while (i && \
+                               ((topaz_priv->topaz_cmd_count - 1) != \
+                                *(topaz_priv->topaz_mtx_wb + \
+                                        core_id * MTX_WRITEBACK_DATASIZE_ROUND\
+                                        + MTX_WRITEBACK_VALUE))) {
+                       cpu_relax();
+                       i--;
+               }
+
+               if (0 != i) {
+                       PSB_DEBUG_GENERAL("TOPAZ: Finished.\n");
+                       break;
+               }
+       }
+
+       if (j == TOPAZ_KICK_RETRY_MAX)
+               DRM_ERROR("TOPAZ:Have toggled MTX kick %d times but all "\
+                               "failed!\n",
+                               TOPAZ_KICK_RETRY_MAX);
+       return;
+}
+
+int pnw_topaz_restore_mtx_state(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       int32_t core_id;
+       uint32_t *mtx_reg_state;
+       int i, need_restore;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       struct psb_video_ctx *pos, *n;
+       uint32_t wb_offset;
+
+       if (!topaz_priv->topaz_mtx_saved)
+               return -1;
+
+       list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+               if ((pos->ctx_type & 0xff) == 6)
+                       need_restore = 1;
+       }
+
+       if (0 == need_restore) {
+               topaz_priv->topaz_mtx_saved = 0;
+               PSB_DEBUG_GENERAL("topaz: no vec context found. needn't"
+                                 " to restore mtx registers.\n");
+               return 0;
+       }
+
+       if (topaz_priv->topaz_fw_loaded == 0) {
+               PSB_DEBUG_GENERAL("TOPAZ: needn't to restore context"
+                                 " without firmware uploaded\n");
+               return 0;
+       }
+
+       if (topaz_priv->topaz_mtx_data_mem[0] == NULL) {
+               PSB_DEBUG_GENERAL("TOPAZ: try to restore context"
+                                 " without space allocated, return"
+                                 " directly without restore\n");
+               return -1;
+       }
+
+       pnw_topaz_mmu_flushcache(dev_priv);
+
+       /*TopazSC will be reset, no need to save context.*/
+       for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++)
+               pnw_topaz_mmu_hwsetup(dev_priv, core_id);
+       for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                               F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                               F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                               F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                               F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                               |
+                               F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                               F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                               core_id);
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                               F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                               F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                               F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                               F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                               |
+                               F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                               F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                               core_id);
+       }
+
+       for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++)
+               pnw_topaz_mmu_hwsetup(dev_priv, core_id);
+
+       for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+               pnw_topazsc_reset_ESB(dev_priv, core_id);
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                            |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                            F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                            core_id);
+               MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+                            |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+                            F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+                            core_id);
+       }
+
+       for (core_id = topaz_priv->topaz_num_cores - 1;
+            core_id >= 0; core_id--) {
+               topaz_set_mtx_target(dev_priv, core_id, 0);
+
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+                               F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET)
+                               |
+                               F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET) |
+                               F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET) |
+                               F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET) |
+                               F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET),
+                               core_id);
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+                       0,
+                       core_id);
+
+               topaz_set_mtx_target(dev_priv, core_id, 0);
+               MTX_WRITE32(MTX_CORE_CR_MTX_SOFT_RESET_OFFSET,
+                       MTX_CORE_CR_MTX_SOFT_RESET_MTX_RESET_MASK,
+                       core_id);
+               MTX_WRITE32(MTX_CORE_CR_MTX_SOFT_RESET_OFFSET,
+                       0, core_id);
+
+               /* # upload fw by drm */
+               PSB_DEBUG_GENERAL("TOPAZ: Restore text and data for core %d\n",
+                                 core_id);
+               if (0 != mtx_dma_write(dev, core_id))
+                       return -1;
+
+               pnw_topaz_mmu_flushcache(dev_priv);
+       }
+
+       for (core_id = topaz_priv->topaz_num_cores - 1;
+                       core_id >= 0; core_id--) {
+               topaz_set_mtx_target(dev_priv, core_id, 0);
+
+               /*Reset IO again. WA for BZ1478*/
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+                               F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET),
+                               core_id);
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+                               0,
+                               core_id);
+
+               mtx_reg_state = topaz_priv->topaz_mtx_reg_state[core_id];
+               /* restore register */
+               /* Saves 8 Registers of D0 Bank  */
+               /* DoRe0, D0Ar6, D0Ar4, D0Ar2, D0FrT, D0.5, D0.6 and D0.7 */
+               for (i = 0; i < 8; i++) {
+                       topaz_write_core_reg(dev_priv, core_id, 0x1 | (i << 4),
+                                            *mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves 8 Registers of D1 Bank  */
+               /* D1Re0, D1Ar5, D1Ar3, D1Ar1, D1RtP, D1.5, D1.6 and D1.7 */
+               for (i = 0; i < 8; i++) {
+                       topaz_write_core_reg(dev_priv, core_id, 0x2 | (i << 4),
+                                            *mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves 4 Registers of A0 Bank  */
+               /* A0StP, A0FrP, A0.2 and A0.3 */
+               for (i = 0; i < 4; i++) {
+                       topaz_write_core_reg(dev_priv, core_id, 0x3 | (i << 4),
+                                            *mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves 4 Registers of A1 Bank  */
+               /* A1GbP, A1LbP, A1.2 and A1.3 */
+               for (i = 0; i < 4; i++) {
+                       topaz_write_core_reg(dev_priv, core_id, 0x4 | (i << 4),
+                                            *mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves PC and PCX  */
+               for (i = 0; i < 2; i++) {
+                       topaz_write_core_reg(dev_priv, core_id, 0x5 | (i << 4),
+                                            *mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves 8 Control Registers */
+               /* TXSTAT, TXMASK, TXSTATI, TXMASKI, TXPOLL, TXGPIOI, TXPOLLI,
+                * TXGPIOO */
+               for (i = 1; i < 8; i += 2) {
+                       /*Force the busy bit of core 0 to be 1. Since idle
+                        * signal may cause the clock to the MTX is not running
+                        * when the kick is written to it. WA for BZ1478.*/
+                       if (i == 7 && core_id == 0)
+                               topaz_write_core_reg(dev_priv, core_id,
+                                               0x7 | (i << 4),
+                                               0x2 | (*mtx_reg_state));
+                       else
+                               topaz_write_core_reg(dev_priv, core_id,
+                                               0x7 | (i << 4),
+                                               *mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               COMMS_WRITE32(TOPAZ_COMMS_CR_STAT_1(0), \
+                               *mtx_reg_state++, core_id);
+               COMMS_WRITE32(TOPAZ_COMMS_CR_STAT_0(0), \
+                               *mtx_reg_state++, core_id);
+               COMMS_WRITE32(TOPAZ_COMMS_CR_MTX_STATUS(0), \
+                               *mtx_reg_state++, core_id);
+               COMMS_WRITE32(TOPAZ_COMMS_CR_CMD_WB_VAL(0), \
+                               *mtx_reg_state++, core_id);
+               COMMS_WRITE32(TOPAZ_COMMS_CR_CMD_WB_ADDR(0), \
+                               *mtx_reg_state++, core_id);
+               COMMS_WRITE32(TOPAZ_COMMS_CR_CMD_DATA_ADDR(0), \
+                               *mtx_reg_state++, core_id);
+               COMMS_WRITE32(TOPAZ_COMMS_CR_CMD_WORD(0), \
+                               *mtx_reg_state++, core_id);
+
+               /* enable auto clock is essential for this driver */
+               TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_AUTO_CLK_GATE,
+                             F_ENCODE(1, TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE) |
+                             F_ENCODE(1, TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE),
+                             core_id);
+               MVEA_WRITE32(MVEA_CR_MVEA_AUTO_CLOCK_GATING,
+                            F_ENCODE(1, MVEA_CR_MVEA_IPE_AUTO_CLK_GATE) |
+                            F_ENCODE(1, MVEA_CR_MVEA_SPE_AUTO_CLK_GATE) |
+                            F_ENCODE(1, MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE) |
+                            F_ENCODE(1, MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE),
+                            core_id);
+
+               topaz_read_core_reg(dev_priv, core_id,
+                       TOPAZ_MTX_PC, &i);
+
+               PSB_DEBUG_GENERAL("TOPAZ: verify pc address for core"
+                       " (%d):0x%08x\n",
+                       core_id, i);
+
+               /* flush the command FIFO - only has effect on master MTX */
+               if (core_id == 0)
+                       TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_CMD_FIFO_2,
+                                     F_ENCODE(1, TOPAZ_CR_CMD_FIFO_FLUSH),
+                                     0);
+
+               /* clear MTX interrupt */
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR,
+                             F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX),
+                             core_id);
+
+               /* put the number of cores in use in the scratch register
+                * so is is ready when the firmware wakes up. */
+               TOPAZ_WRITE32(TOPAZ_CORE_NUMBER_SET_OFFSET, 2, core_id);
+
+               /* # turn on MTX */
+               topaz_set_mtx_target(dev_priv, core_id, 0);
+               MTX_WRITE32(MTX_CORE_CR_MTX_ENABLE_OFFSET,
+                           MTX_CORE_CR_MTX_ENABLE_MTX_ENABLE_MASK,
+                           core_id);
+
+       }
+       PSB_DEBUG_GENERAL("TOPAZ: send NULL command to test firmware\n");
+
+       /*WA for BZ1478. Enable IRQ here, since it's disabled by IO reset*/
+       pnw_topaz_enableirq(dev);
+       TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_CMD_FIFO_1,
+                               F_ENCODE(1, TOPAZ_CR_CMD_FIFO_FLUSH),
+                               0);
+
+       for (core_id = topaz_priv->topaz_num_cores - 1;
+                       core_id >= 0; core_id--) {
+               wb_offset = TOPAZ_MTX_WB_OFFSET(
+                               topaz_priv->topaz_wb_offset,
+                               core_id);
+
+               pnw_topaz_kick_null_cmd(dev_priv, core_id,
+                                         wb_offset,
+                                         topaz_priv->topaz_cmd_count++, 0);
+
+               i = 3000;
+               PSB_DEBUG_GENERAL("TOPAZ: Wait for the NULL command...\n");
+               while (i && \
+                               ((topaz_priv->topaz_cmd_count - 1) != \
+                                *(topaz_priv->topaz_mtx_wb + \
+                                        core_id * MTX_WRITEBACK_DATASIZE_ROUND\
+                                        + MTX_WRITEBACK_VALUE))) {
+                       cpu_relax();
+                       i--;
+               }
+
+               if (i == 0)
+                       pnw_topaz_retry_kick(dev, core_id);
+               else
+                       PSB_DEBUG_GENERAL("TOPAZ:Finished.\n");
+
+               TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR,
+                               F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX),
+                               core_id);
+       }
+
+       topaz_priv->topaz_mtx_saved = 0;
+       return 0;
+}
+
+int pnw_topaz_save_mtx_state(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       uint32_t *mtx_reg_state;
+       int i, need_save = 0;
+       uint32_t data_location, data_size;
+       int core;
+       struct pnw_topaz_codec_fw *cur_codec_fw;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       struct psb_video_ctx *pos, *n;
+       uint32_t reg_val;
+       int j;
+
+       topaz_priv->topaz_mtx_saved = 0;
+
+       list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+               if ((pos->ctx_type & 0xff) == 6)
+                       need_save = 1;
+       }
+
+       if (0 == need_save) {
+               PSB_DEBUG_GENERAL("TOPAZ: vec context not found. No need"
+                                 " to save mtx registers.\n");
+               return 0;
+       }
+
+       /*TopazSC will be reset, no need to save context.*/
+       if (topaz_priv->topaz_needs_reset)
+               return 0;
+
+       PSB_DEBUG_GENERAL("TOPAZ: Found one vec context. "
+                         "Need to save mtx registers.\n");
+       if (topaz_priv->topaz_num_cores > MAX_TOPAZ_CORES) {
+               DRM_ERROR("TOPAZ: Invalid core numbers: %d\n",
+                         topaz_priv->topaz_num_cores);
+               return -1;
+       }
+
+       if (topaz_priv->topaz_fw_loaded == 0) {
+               PSB_DEBUG_GENERAL("TOPAZ: No need to restore context since"
+                                 " firmware has not been uploaded.\n");
+               return -1;
+       }
+
+       for (core = topaz_priv->topaz_num_cores - 1; core >= 0; core--) {
+               if (topaz_priv->topaz_mtx_data_mem[core] == NULL) {
+                       PSB_DEBUG_GENERAL("TOPAZ: try to save context "
+                                         "without space allocated, return"
+                                         " directly without save\n");
+                       return -1;
+               }
+
+               topaz_set_mtx_target(dev_priv, core, 0);
+               /* stop mtx */
+               MTX_WRITE32(MTX_CORE_CR_MTX_ENABLE_OFFSET,
+                               MTX_CORE_CR_MTX_ENABLE_MTX_TOFF_MASK, core);
+
+               if (core == 0) {
+                       if (0 != pnw_topaz_wait_for_register(dev_priv,
+                                                            REG_START_TOPAZ_MTX_HOST(core)
+                                                            + MTX_CORE_CR_MTX_TXRPT_OFFSET,
+                                                            TXRPT_WAITONKICK_VALUE,
+                                                            0xffffffff)) {
+                               DRM_ERROR("TOPAZ: Stop MTX failed!\n");
+                               topaz_priv->topaz_needs_reset = 1;
+                               return -1;
+                       }
+               }
+
+               mtx_reg_state = topaz_priv->topaz_mtx_reg_state[core];
+
+               /* Saves 8 Registers of D0 Bank  */
+               /* DoRe0, D0Ar6, D0Ar4, D0Ar2, D0FrT, D0.5, D0.6 and D0.7 */
+               for (i = 0; i < 8; i++) {
+                       topaz_read_core_reg(dev_priv, core, 0x1 | (i << 4),
+                                           mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves 8 Registers of D1 Bank  */
+               /* D1Re0, D1Ar5, D1Ar3, D1Ar1, D1RtP, D1.5, D1.6 and D1.7 */
+               for (i = 0; i < 8; i++) {
+                       topaz_read_core_reg(dev_priv, core, 0x2 | (i << 4),
+                                           mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves 4 Registers of A0 Bank  */
+               /* A0StP, A0FrP, A0.2 and A0.3 */
+               for (i = 0; i < 4; i++) {
+                       topaz_read_core_reg(dev_priv, core, 0x3 | (i << 4),
+                                           mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves 4 Registers of A1 Bank  */
+               /* A1GbP, A1LbP, A1.2 and A1.3 */
+               for (i = 0; i < 4; i++) {
+                       topaz_read_core_reg(dev_priv, core, 0x4 | (i << 4),
+                                           mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves PC and PCX  */
+               for (i = 0; i < 2; i++) {
+                       topaz_read_core_reg(dev_priv, core, 0x5 | (i << 4),
+                                           mtx_reg_state);
+                       mtx_reg_state++;
+               }
+               /* Saves 8 Control Registers */
+               /* TXSTAT, TXMASK, TXSTATI, TXMASKI, TXPOLL, TXGPIOI, TXPOLLI,
+                * TXGPIOO */
+               for (i = 1; i < 8; i += 2) {
+                       topaz_read_core_reg(dev_priv, core, 0x7 | (i << 4),
+                                           mtx_reg_state);
+                       mtx_reg_state++;
+               }
+
+               COMMS_READ32(TOPAZ_COMMS_CR_STAT_1(0), \
+                               mtx_reg_state++, core);
+               COMMS_READ32(TOPAZ_COMMS_CR_STAT_0(0), \
+                               mtx_reg_state++, core);
+               COMMS_READ32(TOPAZ_COMMS_CR_MTX_STATUS(0), \
+                               mtx_reg_state++, core);
+               COMMS_READ32(TOPAZ_COMMS_CR_CMD_WB_VAL(0), \
+                               mtx_reg_state++, core);
+               COMMS_READ32(TOPAZ_COMMS_CR_CMD_WB_ADDR(0), \
+                               mtx_reg_state++, core);
+               COMMS_READ32(TOPAZ_COMMS_CR_CMD_DATA_ADDR(0), \
+                               mtx_reg_state++, core);
+               COMMS_READ32(TOPAZ_COMMS_CR_CMD_WORD(0), \
+                               mtx_reg_state++, core);
+
+               /* save mtx data memory */
+               if (0 == core) {
+                       /*master core*/
+                       cur_codec_fw = &topaz_priv->topaz_fw[
+                                              topaz_priv->topaz_cur_codec * 2];
+               } else {
+                       cur_codec_fw = &topaz_priv->topaz_fw[
+                                              topaz_priv->topaz_cur_codec * 2 \
+                                              + 1];
+               }
+
+               data_size = cur_codec_fw->data_size / 4;
+               data_size = ((data_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+                            & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+               data_location = cur_codec_fw->data_location
+                               & ~(MTX_DMA_BURSTSIZE_BYTES - 1);
+               if (0 != mtx_dma_read(dev, core,
+                                     data_location,
+                                     data_size)) {
+                       DRM_ERROR("TOPAZ: mtx_dma_read failed!\n");
+                       return -1;
+               }
+               pnw_topaz_mmu_flushcache(dev_priv);
+       }
+
+       TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0,
+                       0x2, 0);
+       /*Make sure there is no pending memory request.*/
+       j = 0;
+       for (i = 0; i < 10000; i++) {
+               TOPAZ_READ32(TOPAZ_CR_MMU_MEM_REQ, &reg_val, 0);
+               if (reg_val == 0)
+                       j++;
+               if (j >= 100)
+                       break;
+       }
+       if (i >= 10000)
+               DRM_ERROR("Polling TOPAZ_CR_MMU_MEM_REQ timeout\n");
+
+       topaz_priv->topaz_mtx_saved = 1;
+
+       return 0;
+}
+
+static int mtx_dma_read(struct drm_device *dev, uint32_t core,
+                uint32_t source_addr, uint32_t size)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct ttm_buffer_object *target;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       /* setup mtx DMAC registers to do transfer */
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA, source_addr, core);
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+                   F_ENCODE(4, MTX_BURSTSIZE) |
+                   F_ENCODE(1, MTX_RNW) |
+                   F_ENCODE(1, MTX_ENABLE) |
+                   F_ENCODE(size, MTX_LENGTH), core);
+
+       /* give the DMAC access to the host memory via BIF */
+       /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, 0);*/
+
+       target = topaz_priv->topaz_mtx_data_mem[core];
+       /* transfert the data */
+       if (0 != topaz_dma_transfer(dev_priv, 0, target->offset, 0,
+                                   MTX_CR_MTX_SYSC_CDMAT,
+                                   size, core, 1)) {
+               pnw_error_dump_reg(dev_priv, core);
+               return -1;
+       }
+
+       /* wait for it transfer */
+       if (0 != pnw_topaz_wait_for_register(dev_priv,
+                               IMG_SOC_DMAC_IRQ_STAT(0) + DMAC_START,
+                               F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+                               F_ENCODE(1, IMG_SOC_TRANSFER_FIN))) {
+               pnw_error_dump_reg(dev_priv, core);
+               return -1;
+       }
+
+       /* clear interrupt */
+       DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+       /* give access back to topaz core */
+       /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, 0);*/
+       return 0;
+}
+
+static int mtx_dma_write(struct drm_device *dev, uint32_t core_id)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+       struct pnw_topaz_codec_fw *cur_codec_fw;
+       uint32_t text_size, data_size;
+       uint32_t data_location;
+       int ret = 0;
+
+       if (core_id == 0)/*for master core*/
+               cur_codec_fw = &topaz_priv->topaz_fw[
+                                      topaz_priv->topaz_cur_codec * 2];
+       else
+               cur_codec_fw = &topaz_priv->topaz_fw[
+                                      topaz_priv->topaz_cur_codec * 2 + 1];
+
+       PSB_DEBUG_GENERAL("Topaz: Restore codec %s(%d) text sz=%d data sz=%d\n"
+                         "data location(0x%x) to core(%d).\n",
+                         codec_to_string(topaz_priv->topaz_cur_codec),
+                         topaz_priv->topaz_cur_codec,
+                         cur_codec_fw->text_size, cur_codec_fw->data_size,
+                         cur_codec_fw->data_location, core_id);
+
+       /* # upload text. text_size is byte size*/
+       text_size = cur_codec_fw->text_size / 4;
+       /* adjust transfer sizes of text and data sections to match burst size*/
+       text_size = ((text_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+                    & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+       PSB_DEBUG_GENERAL("TOPAZ: text_size round up to %d\n", text_size);
+       /* setup the MTX to start recieving data:
+          use a register for the transfer which will point to the source
+          (MTX_CR_MTX_SYSC_CDMAT) */
+       /*MTX burst size (4 * 2 * 32bits = 32bytes) should match DMA burst
+         size (2 * 128bits = 32bytes) */
+       /* #.# fill the dst addr */
+
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA, MTX_DMA_MEMORY_BASE, core_id);
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+                   F_ENCODE(4, MTX_BURSTSIZE) |
+                   F_ENCODE(0, MTX_RNW) |
+                   F_ENCODE(1, MTX_ENABLE) |
+                   F_ENCODE(text_size, MTX_LENGTH), core_id);
+
+       /* #.# set DMAC access to host memory via BIF (deserted)*/
+       /* TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, core_id);*/
+
+       /* #.# transfer the codec */
+       if (0 != topaz_dma_transfer(dev_priv, 0, cur_codec_fw->text->offset, 0,
+                                   MTX_CR_MTX_SYSC_CDMAT,
+                                   text_size, core_id, 0)) {
+               pnw_error_dump_reg(dev_priv, core_id);
+               return -1;
+       }
+
+       /* #.# wait dma finish */
+       ret = pnw_topaz_wait_for_register(dev_priv,
+                                         DMAC_START + IMG_SOC_DMAC_IRQ_STAT(0),
+                                         F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+                                         F_ENCODE(1, IMG_SOC_TRANSFER_FIN));
+       if (ret != 0) {
+               pnw_error_dump_reg(dev_priv, core_id);
+               return -1;
+       }
+
+       /* #.# clear interrupt */
+       DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+
+       PSB_DEBUG_GENERAL("TOPAZ: firmware text upload complete.\n");
+
+       /* # return access to topaz core (deserted)*/
+       /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, core_id);*/
+
+       /* # upload data */
+       data_size = cur_codec_fw->data_size / 4;
+       data_size = ((data_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+                    & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+       data_location = cur_codec_fw->data_location;
+       data_location = data_location & (~(MTX_DMA_BURSTSIZE_BYTES - 1));
+
+       PSB_DEBUG_GENERAL("TOPAZ: data_size round up to %d\n"
+                         "data_location round up to 0x%08x\n",
+                         data_size, data_location);
+       /* #.# fill the dst addr */
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA,
+                   data_location, core_id);
+       MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+                   F_ENCODE(4, MTX_BURSTSIZE) |
+                   F_ENCODE(0, MTX_RNW) |
+                   F_ENCODE(1, MTX_ENABLE) |
+                   F_ENCODE(data_size, MTX_LENGTH), core_id);
+       /* #.# set DMAC access to host memory via BIF(deserted) */
+       /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, core_id);*/
+
+       /* #.# transfer the codec */
+       if (0 != topaz_dma_transfer(dev_priv, 0,
+                               topaz_priv->topaz_mtx_data_mem[core_id]->offset,
+                               0,
+                               MTX_CR_MTX_SYSC_CDMAT, data_size, core_id, 0)) {
+               pnw_error_dump_reg(dev_priv, core_id);
+               return -1;
+       }
+
+       /* #.# wait dma finish */
+       ret = pnw_topaz_wait_for_register(dev_priv,
+                                         DMAC_START + IMG_SOC_DMAC_IRQ_STAT(0),
+                                         F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+                                         F_ENCODE(1, IMG_SOC_TRANSFER_FIN));
+       if (ret != 0) {
+               pnw_error_dump_reg(dev_priv, core_id);
+               return -1;
+       }
+       /* #.# clear interrupt */
+       DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+
+       PSB_DEBUG_GENERAL("TOPAZ: firmware text upload complete.\n");
+
+       /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, 0);*/
+       return 0;
+}
+
+
+void pnw_reset_fw_status(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+       /*Before end the session, mark firmware MTX data as invalid.*/
+       topaz_priv->topaz_mtx_saved = 0;
+
+}
diff --git a/drivers/staging/mrst/imgv/psb_buffer.c b/drivers/staging/mrst/imgv/psb_buffer.c
new file mode 100644 (file)
index 0000000..6f23df7
--- /dev/null
@@ -0,0 +1,441 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ */
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_execbuf_util.h"
+#include "psb_ttm_fence_api.h"
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_schedule.h"
+
+#define DRM_MEM_TTM       26
+
+struct drm_psb_ttm_backend {
+       struct ttm_backend base;
+       struct page **pages;
+       unsigned int desired_tile_stride;
+       unsigned int hw_tile_stride;
+       int mem_type;
+       unsigned long offset;
+       unsigned long num_pages;
+};
+
+/*
+ * MSVDX/TOPAZ GPU virtual space looks like this
+ * (We currently use only one MMU context).
+ * PSB_MEM_MMU_START: from 0x00000000~0xe000000, for generic buffers
+ * TTM_PL_CI: from 0xe0000000+half GTT space, for camear/video buffer sharing
+ * TTM_PL_RAR: from TTM_PL_CI+CI size, for RAR/video buffer sharing
+ * TTM_PL_TT: from TTM_PL_RAR+RAR size, for buffers need to mapping into GTT
+ */
+static int psb_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+                            struct ttm_mem_type_manager *man)
+{
+
+       struct drm_psb_private *dev_priv =
+               container_of(bdev, struct drm_psb_private, bdev);
+       struct psb_gtt *pg = dev_priv->pg;
+
+       switch (type) {
+       case TTM_PL_SYSTEM:
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+               man->available_caching = TTM_PL_FLAG_CACHED |
+                                        TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+               man->default_caching = TTM_PL_FLAG_CACHED;
+               break;
+       case DRM_PSB_MEM_MMU:
+               man->func = &ttm_bo_manager_func;
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+                            TTM_MEMTYPE_FLAG_CMA;
+               man->gpu_offset = PSB_MEM_MMU_START;
+               man->available_caching = TTM_PL_FLAG_CACHED |
+                                        TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+               man->default_caching = TTM_PL_FLAG_WC;
+               break;
+       case TTM_PL_CI:
+               man->func = &ttm_bo_manager_func;
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+                            TTM_MEMTYPE_FLAG_FIXED;
+               man->gpu_offset = pg->mmu_gatt_start + (pg->ci_start);
+               man->available_caching = TTM_PL_FLAG_UNCACHED;
+               man->default_caching = TTM_PL_FLAG_UNCACHED;
+               break;
+       case TTM_PL_RAR:        /* Unmappable RAR memory */
+               man->func = &ttm_bo_manager_func;
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+                            TTM_MEMTYPE_FLAG_FIXED;
+               man->available_caching = TTM_PL_FLAG_UNCACHED;
+               man->default_caching = TTM_PL_FLAG_UNCACHED;
+               man->gpu_offset = pg->mmu_gatt_start + (pg->rar_start);
+               break;
+       case TTM_PL_TT: /* Mappable GATT memory */
+               man->func = &ttm_bo_manager_func;
+#ifdef PSB_WORKING_HOST_MMU_ACCESS
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+#else
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+                            TTM_MEMTYPE_FLAG_CMA;
+#endif
+               man->available_caching = TTM_PL_FLAG_CACHED |
+                                        TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+               man->default_caching = TTM_PL_FLAG_WC;
+               man->gpu_offset = pg->mmu_gatt_start + (pg->rar_start + dev_priv->rar_region_size);
+               break;
+       default:
+               DRM_ERROR("Unsupported memory type %u\n", (unsigned) type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+
+static void psb_evict_mask(struct ttm_buffer_object *bo, struct ttm_placement* placement)
+{
+       static uint32_t cur_placement;
+
+       cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEM;
+       cur_placement |= TTM_PL_FLAG_SYSTEM;
+
+       placement->fpfn = 0;
+       placement->lpfn = 0;
+       placement->num_placement = 1;
+       placement->placement = &cur_placement;
+       placement->num_busy_placement = 0;
+       placement->busy_placement = NULL;
+
+       /* all buffers evicted to system memory */
+       /* return cur_placement | TTM_PL_FLAG_SYSTEM; */
+}
+
+static int psb_invalidate_caches(struct ttm_bo_device *bdev,
+                                uint32_t placement)
+{
+       return 0;
+}
+
+static int psb_move_blit(struct ttm_buffer_object *bo,
+                        bool evict, bool no_wait,
+                        struct ttm_mem_reg *new_mem)
+{
+       BUG();
+       return 0;
+}
+
+/*
+ * Flip destination ttm into GATT,
+ * then blit and subsequently move out again.
+ */
+
+static int psb_move_flip(struct ttm_buffer_object *bo,
+                        bool evict, bool interruptible, bool no_wait,
+                        struct ttm_mem_reg *new_mem)
+{
+       /*struct ttm_bo_device *bdev = bo->bdev;*/
+       struct ttm_mem_reg tmp_mem;
+       int ret;
+       struct ttm_placement placement;
+       uint32_t flags = TTM_PL_FLAG_TT;
+
+       tmp_mem = *new_mem;
+       tmp_mem.mm_node = NULL;
+
+       placement.fpfn = 0;
+       placement.lpfn = 0;
+       placement.num_placement = 1;
+       placement.placement = &flags;
+       placement.num_busy_placement = 0; /* FIXME */
+       placement.busy_placement = NULL;
+
+       ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, false, no_wait);
+       if (ret)
+               return ret;
+       ret = ttm_tt_bind(bo->ttm, &tmp_mem);
+       if (ret)
+               goto out_cleanup;
+       ret = psb_move_blit(bo, true, no_wait, &tmp_mem);
+       if (ret)
+               goto out_cleanup;
+
+       ret = ttm_bo_move_ttm(bo, evict, false, no_wait, new_mem);
+out_cleanup:
+       if (tmp_mem.mm_node) {
+               /*spin_lock(&bdev->lru_lock);*/ // lru_lock is removed from upstream TTM
+               drm_mm_put_block(tmp_mem.mm_node);
+               tmp_mem.mm_node = NULL;
+               /*spin_unlock(&bdev->lru_lock);*/
+       }
+       return ret;
+}
+
+static int psb_move(struct ttm_buffer_object *bo,
+                   bool evict, bool interruptible, bool no_wait_reserve,
+                   bool no_wait, struct ttm_mem_reg *new_mem)
+{
+       struct ttm_mem_reg *old_mem = &bo->mem;
+
+       if ((old_mem->mem_type == TTM_PL_RAR) ||
+           (new_mem->mem_type == TTM_PL_RAR)) {
+               if (old_mem->mm_node) {
+                       spin_lock(&bo->glob->lru_lock);
+                       drm_mm_put_block(old_mem->mm_node);
+                       spin_unlock(&bo->glob->lru_lock);
+               }
+               old_mem->mm_node = NULL;
+               *old_mem = *new_mem;
+       } else if (old_mem->mem_type == TTM_PL_SYSTEM) {
+               return ttm_bo_move_memcpy(bo, evict, false, no_wait, new_mem);
+       } else if (new_mem->mem_type == TTM_PL_SYSTEM) {
+               int ret = psb_move_flip(bo, evict, interruptible,
+                                       no_wait, new_mem);
+               if (unlikely(ret != 0)) {
+                       if (ret == -ERESTART)
+                               return ret;
+                       else
+                               return ttm_bo_move_memcpy(bo, evict, false, no_wait,
+                                                         new_mem);
+               }
+       } else {
+               if (psb_move_blit(bo, evict, no_wait, new_mem))
+                       return ttm_bo_move_memcpy(bo, evict, false, no_wait,
+                                                 new_mem);
+       }
+       return 0;
+}
+
+/* REVISIT: is there a need to use the dma_addrs or other parameters? */
+static int drm_psb_tbe_populate(struct ttm_backend *backend,
+                               unsigned long num_pages,
+                               struct page **pages,
+                               struct page *dummy_read_page,
+                               dma_addr_t *dma_addrs)
+{
+       struct drm_psb_ttm_backend *psb_be =
+               container_of(backend, struct drm_psb_ttm_backend, base);
+
+       psb_be->pages = pages;
+       return 0;
+}
+
+static int drm_psb_tbe_unbind(struct ttm_backend *backend)
+{
+       struct ttm_bo_device *bdev = backend->bdev;
+       struct drm_psb_private *dev_priv =
+               container_of(bdev, struct drm_psb_private, bdev);
+       struct drm_psb_ttm_backend *psb_be =
+               container_of(backend, struct drm_psb_ttm_backend, base);
+       struct psb_mmu_pd *pd = psb_mmu_get_default_pd(dev_priv->mmu);
+       /* struct ttm_mem_type_manager *man = &bdev->man[psb_be->mem_type]; */
+
+       if (psb_be->mem_type == TTM_PL_TT) {
+               uint32_t gatt_p_offset =
+                       (psb_be->offset - dev_priv->pg->mmu_gatt_start) >> PAGE_SHIFT;
+
+               (void) psb_gtt_remove_pages(dev_priv->pg, gatt_p_offset,
+                                           psb_be->num_pages,
+                                           psb_be->desired_tile_stride,
+                                           psb_be->hw_tile_stride, 0);
+       }
+
+       psb_mmu_remove_pages(pd, psb_be->offset,
+                            psb_be->num_pages,
+                            psb_be->desired_tile_stride,
+                            psb_be->hw_tile_stride);
+
+       return 0;
+}
+
+static int drm_psb_tbe_bind(struct ttm_backend *backend,
+                           struct ttm_mem_reg *bo_mem)
+{
+       struct ttm_bo_device *bdev = backend->bdev;
+       struct drm_psb_private *dev_priv =
+               container_of(bdev, struct drm_psb_private, bdev);
+       struct drm_psb_ttm_backend *psb_be =
+               container_of(backend, struct drm_psb_ttm_backend, base);
+       struct psb_mmu_pd *pd = psb_mmu_get_default_pd(dev_priv->mmu);
+       struct ttm_mem_type_manager *man = &bdev->man[bo_mem->mem_type];
+       int type;
+       int ret = 0;
+
+       psb_be->mem_type = bo_mem->mem_type;
+       psb_be->num_pages = bo_mem->num_pages;
+       psb_be->desired_tile_stride = 0;
+       psb_be->hw_tile_stride = 0;
+       psb_be->offset = (bo_mem->start << PAGE_SHIFT) + man->gpu_offset;
+
+       type =
+               (bo_mem->
+                placement & TTM_PL_FLAG_CACHED) ? PSB_MMU_CACHED_MEMORY : 0;
+
+       if (psb_be->mem_type == TTM_PL_TT) {
+               uint32_t gatt_p_offset =
+                       (psb_be->offset - dev_priv->pg->mmu_gatt_start) >> PAGE_SHIFT;
+
+               ret = psb_gtt_insert_pages(dev_priv->pg, psb_be->pages,
+                                          gatt_p_offset,
+                                          psb_be->num_pages,
+                                          psb_be->desired_tile_stride,
+                                          psb_be->hw_tile_stride, type);
+       }
+
+       ret = psb_mmu_insert_pages(pd, psb_be->pages,
+                                  psb_be->offset, psb_be->num_pages,
+                                  psb_be->desired_tile_stride,
+                                  psb_be->hw_tile_stride, type);
+       if (ret)
+               goto out_err;
+
+       return 0;
+out_err:
+       drm_psb_tbe_unbind(backend);
+       return ret;
+
+}
+
+static void drm_psb_tbe_clear(struct ttm_backend *backend)
+{
+       struct drm_psb_ttm_backend *psb_be =
+               container_of(backend, struct drm_psb_ttm_backend, base);
+
+       psb_be->pages = NULL;
+       return;
+}
+
+static void drm_psb_tbe_destroy(struct ttm_backend *backend)
+{
+       struct drm_psb_ttm_backend *psb_be =
+               container_of(backend, struct drm_psb_ttm_backend, base);
+
+       if (backend)
+               kfree(psb_be);
+}
+
+static struct ttm_backend_func psb_ttm_backend = {
+       .populate = drm_psb_tbe_populate,
+       .clear = drm_psb_tbe_clear,
+       .bind = drm_psb_tbe_bind,
+       .unbind = drm_psb_tbe_unbind,
+       .destroy = drm_psb_tbe_destroy,
+};
+
+static struct ttm_backend *drm_psb_tbe_init(struct ttm_bo_device *bdev) {
+       struct drm_psb_ttm_backend *psb_be;
+
+       psb_be = kzalloc(sizeof(*psb_be), GFP_KERNEL);
+       if (!psb_be)
+               return NULL;
+       psb_be->pages = NULL;
+       psb_be->base.func = &psb_ttm_backend;
+       psb_be->base.bdev = bdev;
+       return &psb_be->base;
+}
+
+static int psb_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+       struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+       struct drm_psb_private *dev_priv =
+               container_of(bdev, struct drm_psb_private, bdev);
+       struct psb_gtt *pg = dev_priv->pg;
+
+       mem->bus.addr = NULL;
+       mem->bus.offset = 0;
+       mem->bus.size = mem->num_pages << PAGE_SHIFT;
+       mem->bus.base = 0;
+       mem->bus.is_iomem = false;
+       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+               return -EINVAL;
+       switch (mem->mem_type) {
+       case TTM_PL_SYSTEM:
+               /* system memory */
+               return 0;
+       case TTM_PL_TT:
+               mem->bus.offset = mem->start << PAGE_SHIFT;
+               mem->bus.base = pg->gatt_start;
+               mem->bus.is_iomem = false; /* Don't know whether it is IO_MEM, this flag used in vm_fault handle */
+               break;
+       case DRM_PSB_MEM_MMU:
+               mem->bus.offset = mem->start << PAGE_SHIFT;
+               mem->bus.base = 0x00000000;
+               break;
+       case TTM_PL_CI:
+               mem->bus.offset = mem->start << PAGE_SHIFT;
+               mem->bus.base = dev_priv->ci_region_start;;
+               mem->bus.is_iomem = true;
+               break;
+       case TTM_PL_RAR:
+               mem->bus.offset = mem->start << PAGE_SHIFT;
+               mem->bus.base = dev_priv->rar_region_start;;
+               mem->bus.is_iomem = true;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void psb_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+}
+
+/*
+ * Use this memory type priority if no eviction is needed.
+ */
+/*
+static uint32_t psb_mem_prios[] = {
+       TTM_PL_CI,
+       TTM_PL_RAR,
+       TTM_PL_TT,
+       DRM_PSB_MEM_MMU,
+       TTM_PL_SYSTEM
+};
+*/
+/*
+ * Use this memory type priority if need to evict.
+ */
+/*
+static uint32_t psb_busy_prios[] = {
+       TTM_PL_TT,
+       TTM_PL_CI,
+       TTM_PL_RAR,
+       DRM_PSB_MEM_MMU,
+       TTM_PL_SYSTEM
+};
+*/
+struct ttm_bo_driver psb_ttm_bo_driver = {
+       /*
+               .mem_type_prio = psb_mem_prios,
+               .mem_busy_prio = psb_busy_prios,
+               .num_mem_type_prio = ARRAY_SIZE(psb_mem_prios),
+               .num_mem_busy_prio = ARRAY_SIZE(psb_busy_prios),
+       */
+       .create_ttm_backend_entry = &drm_psb_tbe_init,
+       .invalidate_caches = &psb_invalidate_caches,
+       .init_mem_type = &psb_init_mem_type,
+       .evict_flags = &psb_evict_mask,
+       .move = &psb_move,
+       .verify_access = &psb_verify_access,
+       .sync_obj_signaled = &ttm_fence_sync_obj_signaled,
+       .sync_obj_wait = &ttm_fence_sync_obj_wait,
+       .sync_obj_flush = &ttm_fence_sync_obj_flush,
+       .sync_obj_unref = &ttm_fence_sync_obj_unref,
+       .sync_obj_ref = &ttm_fence_sync_obj_ref,
+       .io_mem_reserve = &psb_ttm_io_mem_reserve,
+       .io_mem_free = &psb_ttm_io_mem_free
+};
diff --git a/drivers/staging/mrst/imgv/psb_fence.c b/drivers/staging/mrst/imgv/psb_fence.c
new file mode 100644 (file)
index 0000000..8ebf7c9
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+
+static void psb_fence_poll(struct ttm_fence_device *fdev,
+                          uint32_t fence_class, uint32_t waiting_types)
+{
+       struct drm_psb_private *dev_priv =
+               container_of(fdev, struct drm_psb_private, fdev);
+       uint32_t sequence = 0;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+
+       if (unlikely(!dev_priv))
+               return;
+
+       if (waiting_types == 0)
+               return;
+
+       switch (fence_class) {
+       case PSB_ENGINE_VIDEO:
+               sequence = msvdx_priv->msvdx_current_sequence;
+               break;
+       case LNC_ENGINE_ENCODE:
+               sequence = *((uint32_t *)
+                       ((struct pnw_topaz_private *)dev_priv->topaz_private)->topaz_sync_addr + 1);
+               break;
+       default:
+               break;
+       }
+
+       /* DRM_ERROR("Polling fence sequence, got 0x%08x\n", sequence); */
+       ttm_fence_handler(fdev, fence_class, sequence,
+                         _PSB_FENCE_TYPE_EXE, 0);
+}
+
+void psb_fence_error(struct drm_device *dev,
+                    uint32_t fence_class,
+                    uint32_t sequence, uint32_t type, int error)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct ttm_fence_device *fdev = &dev_priv->fdev;
+       unsigned long irq_flags;
+       struct ttm_fence_class_manager *fc =
+                               &fdev->fence_class[fence_class];
+
+       BUG_ON(fence_class >= PSB_NUM_ENGINES);
+       write_lock_irqsave(&fc->lock, irq_flags);
+       ttm_fence_handler(fdev, fence_class, sequence, type, error);
+       write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+int psb_fence_emit_sequence(struct ttm_fence_device *fdev,
+                           uint32_t fence_class,
+                           uint32_t flags, uint32_t *sequence,
+                           unsigned long *timeout_jiffies)
+{
+       struct drm_psb_private *dev_priv =
+               container_of(fdev, struct drm_psb_private, fdev);
+       uint32_t seq = 0;
+
+       if (!dev_priv)
+               return -EINVAL;
+
+       if (fence_class >= PSB_NUM_ENGINES)
+               return -EINVAL;
+
+       switch (fence_class) {
+       case PSB_ENGINE_VIDEO:
+               spin_lock(&dev_priv->sequence_lock);
+               seq = dev_priv->sequence[fence_class]++;
+               spin_unlock(&dev_priv->sequence_lock);
+               break;
+       case LNC_ENGINE_ENCODE:
+               spin_lock(&dev_priv->sequence_lock);
+               seq = dev_priv->sequence[fence_class]++;
+               spin_unlock(&dev_priv->sequence_lock);
+               break;
+       default:
+               DRM_ERROR("Unexpected fence class\n");
+               return -EINVAL;
+       }
+
+       *sequence = seq;
+       *timeout_jiffies = jiffies + DRM_HZ * 3;
+
+       return 0;
+}
+
+static void psb_fence_lockup(struct ttm_fence_object *fence,
+                            uint32_t fence_types)
+{
+       struct ttm_fence_device *fdev = fence->fdev;
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+       struct drm_psb_private *dev_priv =
+               container_of(fdev, struct drm_psb_private, fdev);
+       struct drm_device *dev = (struct drm_device *)dev_priv->dev;
+
+       if (fence->fence_class == LNC_ENGINE_ENCODE) {
+               DRM_ERROR("TOPAZ timeout (probable lockup) detected,  flush queued cmdbuf");
+
+               write_lock(&fc->lock);
+               pnw_topaz_handle_timeout(fence->fdev);
+               ttm_fence_handler(fence->fdev, fence->fence_class,
+                                 fence->sequence, fence_types, -EBUSY);
+               write_unlock(&fc->lock);
+       } else if (fence->fence_class == PSB_ENGINE_VIDEO) {
+               struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+               DRM_ERROR("MSVDX timeout (probable lockup) detected, flush queued cmdbuf");
+
+               psb_msvdx_flush_cmd_queue(dev);
+
+               write_lock(&fc->lock);
+               ttm_fence_handler(fence->fdev, fence->fence_class,
+                                 fence->sequence, fence_types, -EBUSY);
+               write_unlock(&fc->lock);
+
+               msvdx_priv->msvdx_needs_reset = 1;
+       } else
+               DRM_ERROR("Unsupported fence class\n");
+}
+
+void psb_fence_handler(struct drm_device *dev, uint32_t fence_class)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct ttm_fence_device *fdev = &dev_priv->fdev;
+       struct ttm_fence_class_manager *fc =
+                               &fdev->fence_class[fence_class];
+       unsigned long irq_flags;
+
+       write_lock_irqsave(&fc->lock, irq_flags);
+       psb_fence_poll(fdev, fence_class, fc->waiting_types);
+       write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+
+static struct ttm_fence_driver psb_ttm_fence_driver = {
+       .has_irq = NULL,
+       .emit = psb_fence_emit_sequence,
+       .flush = NULL,
+       .poll = psb_fence_poll,
+       .needed_flush = NULL,
+       .wait = NULL,
+       .signaled = NULL,
+       .lockup = psb_fence_lockup,
+};
+
+int psb_ttm_fence_device_init(struct ttm_fence_device *fdev)
+{
+       struct drm_psb_private *dev_priv =
+               container_of(fdev, struct drm_psb_private, fdev);
+       struct ttm_fence_class_init fci = {.wrap_diff = (1 << 30),
+               .flush_diff = (1 << 29),
+                .sequence_mask = 0xFFFFFFFF
+                         };
+
+       return ttm_fence_device_init(PSB_NUM_ENGINES,
+                                    dev_priv->mem_global_ref.object,
+                                    fdev, &fci, 1,
+                                    &psb_ttm_fence_driver);
+}
diff --git a/drivers/staging/mrst/imgv/psb_mmu.c b/drivers/staging/mrst/imgv/psb_mmu.c
new file mode 100644 (file)
index 0000000..82b7c62
--- /dev/null
@@ -0,0 +1,1040 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_msvdx.h"
+
+/*
+ * Code for the SGX MMU:
+ */
+
+/*
+ * clflush on one processor only:
+ * clflush should apparently flush the cache line on all processors in an
+ * SMP system.
+ */
+
+/*
+ * kmap atomic:
+ * The usage of the slots must be completely encapsulated within a spinlock, and
+ * no other functions that may be using the locks for other purposed may be
+ * called from within the locked region.
+ * Since the slots are per processor, this will guarantee that we are the only
+ * user.
+ */
+
+/*
+ * TODO: Inserting ptes from an interrupt handler:
+ * This may be desirable for some SGX functionality where the GPU can fault in
+ * needed pages. For that, we need to make an atomic insert_pages function, that
+ * may fail.
+ * If it fails, the caller need to insert the page using a workqueue function,
+ * but on average it should be fast.
+ */
+
+struct psb_mmu_driver {
+       /* protects driver- and pd structures. Always take in read mode
+        * before taking the page table spinlock.
+        */
+       struct rw_semaphore sem;
+
+       /* protects page tables, directory tables and pt tables.
+        * and pt structures.
+        */
+       spinlock_t lock;
+
+       atomic_t needs_tlbflush;
+
+       uint8_t __iomem *register_map;
+       struct psb_mmu_pd *default_pd;
+       /*uint32_t bif_ctrl;*/
+       int has_clflush;
+       int clflush_add;
+       unsigned long clflush_mask;
+
+       struct drm_psb_private *dev_priv;
+};
+
+struct psb_mmu_pd;
+
+struct psb_mmu_pt {
+       struct psb_mmu_pd *pd;
+       uint32_t index;
+       uint32_t count;
+       struct page *p;
+       uint32_t *v;
+};
+
+struct psb_mmu_pd {
+       struct psb_mmu_driver *driver;
+       int hw_context;
+       struct psb_mmu_pt **tables;
+       struct page *p;
+       struct page *dummy_pt;
+       struct page *dummy_page;
+       uint32_t pd_mask;
+       uint32_t invalid_pde;
+       uint32_t invalid_pte;
+};
+
+static inline uint32_t psb_mmu_pt_index(uint32_t offset)
+{
+       return (offset >> PSB_PTE_SHIFT) & 0x3FF;
+}
+
+static inline uint32_t psb_mmu_pd_index(uint32_t offset)
+{
+       return offset >> PSB_PDE_SHIFT;
+}
+
+#if defined(CONFIG_X86)
+static inline void psb_clflush(void *addr)
+{
+       __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
+}
+
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
+                                  void *addr)
+{
+       if (!driver->has_clflush)
+               return;
+
+       mb();
+       psb_clflush(addr);
+       mb();
+}
+
+static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
+{
+       uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
+       uint32_t clflush_count = PAGE_SIZE / clflush_add;
+       int i;
+       uint8_t *clf;
+
+       clf = kmap_atomic(page, KM_USER0);
+       mb();
+       for (i = 0; i < clflush_count; ++i) {
+               psb_clflush(clf);
+               clf += clflush_add;
+       }
+       mb();
+       kunmap_atomic(clf, KM_USER0);
+}
+
+static void psb_pages_clflush(struct psb_mmu_driver *driver, struct page *page[], unsigned long num_pages)
+{
+       int i;
+
+       if (!driver->has_clflush)
+               return ;
+
+       for (i = 0; i < num_pages; i++)
+               psb_page_clflush(driver, *page++);
+}
+#else
+
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
+                                  void *addr)
+{
+       ;
+}
+
+static void psb_pages_clflush(struct psb_mmu_driver *driver, struct page *page[], unsigned long num_pages)
+{
+       printk("Dumy psb_pages_clflush\n");
+}
+
+#endif
+
+static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
+                                   int force)
+{
+       if (atomic_read(&driver->needs_tlbflush) || force) {
+               if (driver->dev_priv) {
+                       atomic_set(&driver->dev_priv->msvdx_mmu_invaldc, 1);
+                       atomic_set(&driver->dev_priv->topaz_mmu_invaldc, 1);
+               }
+       }
+       atomic_set(&driver->needs_tlbflush, 0);
+}
+
+static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
+{
+       down_write(&driver->sem);
+       psb_mmu_flush_pd_locked(driver, force);
+       up_write(&driver->sem);
+}
+
+void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
+{
+       if (rc_prot)
+               down_write(&driver->sem);
+       if (driver->dev_priv) {
+               atomic_set(&driver->dev_priv->msvdx_mmu_invaldc, 1);
+               atomic_set(&driver->dev_priv->topaz_mmu_invaldc, 1);
+       }
+       if (rc_prot)
+               up_write(&driver->sem);
+}
+
+void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
+{
+       /*ttm_tt_cache_flush(&pd->p, 1);*/
+       psb_pages_clflush(pd->driver, &pd->p, 1);
+       down_write(&pd->driver->sem);
+       wmb();
+       psb_mmu_flush_pd_locked(pd->driver, 1);
+       pd->hw_context = hw_context;
+       up_write(&pd->driver->sem);
+
+}
+
+static inline unsigned long psb_pd_addr_end(unsigned long addr,
+               unsigned long end)
+{
+
+       addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
+       return (addr < end) ? addr : end;
+}
+
+static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
+{
+       uint32_t mask = PSB_PTE_VALID;
+
+       if (type & PSB_MMU_CACHED_MEMORY)
+               mask |= PSB_PTE_CACHED;
+       if (type & PSB_MMU_RO_MEMORY)
+               mask |= PSB_PTE_RO;
+       if (type & PSB_MMU_WO_MEMORY)
+               mask |= PSB_PTE_WO;
+
+       return (pfn << PAGE_SHIFT) | mask;
+}
+
+struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+                                   int trap_pagefaults, int invalid_type) {
+       struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+       uint32_t *v;
+       int i;
+
+       if (!pd)
+               return NULL;
+
+       pd->p = alloc_page(GFP_DMA32);
+       if (!pd->p)
+               goto out_err1;
+       pd->dummy_pt = alloc_page(GFP_DMA32);
+       if (!pd->dummy_pt)
+               goto out_err2;
+       pd->dummy_page = alloc_page(GFP_DMA32);
+       if (!pd->dummy_page)
+               goto out_err3;
+
+       if (!trap_pagefaults) {
+               pd->invalid_pde =
+                       psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
+                                        invalid_type);
+               pd->invalid_pte =
+                       psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
+                                        invalid_type);
+       } else {
+               pd->invalid_pde = 0;
+               pd->invalid_pte = 0;
+       }
+
+       v = kmap(pd->dummy_pt);
+       for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+               v[i] = pd->invalid_pte;
+
+       kunmap(pd->dummy_pt);
+
+       v = kmap(pd->p);
+       for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+               v[i] = pd->invalid_pde;
+
+       kunmap(pd->p);
+
+       clear_page(kmap(pd->dummy_page));
+       kunmap(pd->dummy_page);
+
+       pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
+       if (!pd->tables)
+               goto out_err4;
+
+       pd->hw_context = -1;
+       pd->pd_mask = PSB_PTE_VALID;
+       pd->driver = driver;
+
+       return pd;
+
+out_err4:
+       __free_page(pd->dummy_page);
+out_err3:
+       __free_page(pd->dummy_pt);
+out_err2:
+       __free_page(pd->p);
+out_err1:
+       kfree(pd);
+       return NULL;
+}
+
+static void psb_mmu_free_pt(struct psb_mmu_pt *pt)
+{
+       __free_page(pt->p);
+       kfree(pt);
+}
+
+void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
+{
+       struct psb_mmu_driver *driver = pd->driver;
+       struct psb_mmu_pt *pt;
+       int i;
+
+       down_write(&driver->sem);
+       if (pd->hw_context != -1)
+               psb_mmu_flush_pd_locked(driver, 1);
+
+       /* Should take the spinlock here, but we don't need to do that
+          since we have the semaphore in write mode. */
+
+       for (i = 0; i < 1024; ++i) {
+               pt = pd->tables[i];
+               if (pt)
+                       psb_mmu_free_pt(pt);
+       }
+
+       vfree(pd->tables);
+       __free_page(pd->dummy_page);
+       __free_page(pd->dummy_pt);
+       __free_page(pd->p);
+       kfree(pd);
+       up_write(&driver->sem);
+}
+
+static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd) {
+       struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
+       void *v;
+       uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
+       uint32_t clflush_count = PAGE_SIZE / clflush_add;
+       spinlock_t *lock = &pd->driver->lock;
+       uint8_t *clf;
+       uint32_t *ptes;
+       int i;
+
+       if (!pt)
+               return NULL;
+
+       pt->p = alloc_page(GFP_DMA32);
+       if (!pt->p) {
+               kfree(pt);
+               return NULL;
+       }
+
+       spin_lock(lock);
+
+       v = kmap_atomic(pt->p, KM_USER0);
+       clf = (uint8_t *) v;
+       ptes = (uint32_t *) v;
+       for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+               *ptes++ = pd->invalid_pte;
+
+
+#if defined(CONFIG_X86)
+       if (pd->driver->has_clflush && pd->hw_context != -1) {
+               mb();
+               for (i = 0; i < clflush_count; ++i) {
+                       psb_clflush(clf);
+                       clf += clflush_add;
+               }
+               mb();
+       }
+#endif
+       kunmap_atomic(v, KM_USER0);
+       spin_unlock(lock);
+
+       pt->count = 0;
+       pt->pd = pd;
+       pt->index = 0;
+
+       return pt;
+}
+
+static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
+               unsigned long addr) {
+       uint32_t index = psb_mmu_pd_index(addr);
+       struct psb_mmu_pt *pt;
+       uint32_t *v;
+       spinlock_t *lock = &pd->driver->lock;
+
+       spin_lock(lock);
+       pt = pd->tables[index];
+       while (!pt) {
+               spin_unlock(lock);
+               pt = psb_mmu_alloc_pt(pd);
+               if (!pt)
+                       return NULL;
+               spin_lock(lock);
+
+               if (pd->tables[index]) {
+                       spin_unlock(lock);
+                       psb_mmu_free_pt(pt);
+                       spin_lock(lock);
+                       pt = pd->tables[index];
+                       continue;
+               }
+
+               v = kmap_atomic(pd->p, KM_USER0);
+               pd->tables[index] = pt;
+               v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
+               pt->index = index;
+               kunmap_atomic((void *) v, KM_USER0);
+
+               if (pd->hw_context != -1) {
+                       psb_mmu_clflush(pd->driver, (void *) &v[index]);
+                       atomic_set(&pd->driver->needs_tlbflush, 1);
+               }
+       }
+       pt->v = kmap_atomic(pt->p, KM_USER0);
+       return pt;
+}
+
+static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
+               unsigned long addr) {
+       uint32_t index = psb_mmu_pd_index(addr);
+       struct psb_mmu_pt *pt;
+       spinlock_t *lock = &pd->driver->lock;
+
+       spin_lock(lock);
+       pt = pd->tables[index];
+       if (!pt) {
+               spin_unlock(lock);
+               return NULL;
+       }
+       pt->v = kmap_atomic(pt->p, KM_USER0);
+       return pt;
+}
+
+static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
+{
+       struct psb_mmu_pd *pd = pt->pd;
+       uint32_t *v;
+
+       kunmap_atomic(pt->v, KM_USER0);
+       if (pt->count == 0) {
+               v = kmap_atomic(pd->p, KM_USER0);
+               v[pt->index] = pd->invalid_pde;
+               pd->tables[pt->index] = NULL;
+
+               if (pd->hw_context != -1) {
+                       psb_mmu_clflush(pd->driver,
+                                       (void *) &v[pt->index]);
+                       atomic_set(&pd->driver->needs_tlbflush, 1);
+               }
+               kunmap_atomic(pt->v, KM_USER0);
+               spin_unlock(&pd->driver->lock);
+               psb_mmu_free_pt(pt);
+               return;
+       }
+       spin_unlock(&pd->driver->lock);
+}
+
+static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
+                                  unsigned long addr, uint32_t pte)
+{
+       pt->v[psb_mmu_pt_index(addr)] = pte;
+}
+
+static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
+               unsigned long addr)
+{
+       pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
+}
+
+#if 0
+static uint32_t psb_mmu_check_pte_locked(struct psb_mmu_pd *pd,
+               uint32_t mmu_offset)
+{
+       uint32_t *v;
+       uint32_t pfn;
+
+       v = kmap_atomic(pd->p, KM_USER0);
+       if (!v) {
+               printk(KERN_INFO "Could not kmap pde page.\n");
+               return 0;
+       }
+       pfn = v[psb_mmu_pd_index(mmu_offset)];
+       /*      printk(KERN_INFO "pde is 0x%08x\n",pfn); */
+       kunmap_atomic(v, KM_USER0);
+       if (((pfn & 0x0F) != PSB_PTE_VALID)) {
+               printk(KERN_INFO "Strange pde at 0x%08x: 0x%08x.\n",
+                      mmu_offset, pfn);
+       }
+       v = ioremap(pfn & 0xFFFFF000, 4096);
+       if (!v) {
+               printk(KERN_INFO "Could not kmap pte page.\n");
+               return 0;
+       }
+       pfn = v[psb_mmu_pt_index(mmu_offset)];
+       /* printk(KERN_INFO "pte is 0x%08x\n",pfn); */
+       iounmap(v);
+       if (((pfn & 0x0F) != PSB_PTE_VALID)) {
+               printk(KERN_INFO "Strange pte at 0x%08x: 0x%08x.\n",
+                      mmu_offset, pfn);
+       }
+       return pfn >> PAGE_SHIFT;
+}
+
+static void psb_mmu_check_mirrored_gtt(struct psb_mmu_pd *pd,
+                                      uint32_t mmu_offset,
+                                      uint32_t gtt_pages)
+{
+       uint32_t start;
+       uint32_t next;
+
+       printk(KERN_INFO "Checking mirrored gtt 0x%08x %d\n",
+              mmu_offset, gtt_pages);
+       down_read(&pd->driver->sem);
+       start = psb_mmu_check_pte_locked(pd, mmu_offset);
+       mmu_offset += PAGE_SIZE;
+       gtt_pages -= 1;
+       while (gtt_pages--) {
+               next = psb_mmu_check_pte_locked(pd, mmu_offset);
+               if (next != start + 1) {
+                       printk(KERN_INFO
+                              "Ptes out of order: 0x%08x, 0x%08x.\n",
+                              start, next);
+               }
+               start = next;
+               mmu_offset += PAGE_SIZE;
+       }
+       up_read(&pd->driver->sem);
+}
+
+#endif
+
+void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
+                       uint32_t mmu_offset, uint32_t gtt_start,
+                       uint32_t gtt_pages)
+{
+       uint32_t *v;
+       uint32_t start = psb_mmu_pd_index(mmu_offset);
+       struct psb_mmu_driver *driver = pd->driver;
+       int num_pages = gtt_pages;
+
+       down_read(&driver->sem);
+       spin_lock(&driver->lock);
+
+       v = kmap_atomic(pd->p, KM_USER0);
+       v += start;
+
+       while (gtt_pages--) {
+               *v++ = gtt_start | pd->pd_mask;
+               gtt_start += PAGE_SIZE;
+       }
+
+       /*ttm_tt_cache_flush(&pd->p, num_pages);*/
+       psb_pages_clflush(pd->driver, &pd->p, num_pages);
+       kunmap_atomic(v, KM_USER0);
+       spin_unlock(&driver->lock);
+
+       if (pd->hw_context != -1)
+               atomic_set(&pd->driver->needs_tlbflush, 1);
+
+       up_read(&pd->driver->sem);
+       psb_mmu_flush_pd(pd->driver, 0);
+}
+
+struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) {
+       struct psb_mmu_pd *pd;
+
+       /* down_read(&driver->sem); */
+       pd = driver->default_pd;
+       /* up_read(&driver->sem); */
+
+       return pd;
+}
+
+/* Returns the physical address of the PD shared by sgx/msvdx */
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
+{
+       struct psb_mmu_pd *pd;
+
+       pd = psb_mmu_get_default_pd(driver);
+       return page_to_pfn(pd->p) << PAGE_SHIFT;
+}
+
+void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
+{
+       psb_mmu_free_pagedir(driver->default_pd);
+       kfree(driver);
+}
+
+struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+               int trap_pagefaults,
+               int invalid_type,
+               struct drm_psb_private *dev_priv) {
+       struct psb_mmu_driver *driver;
+
+       driver = kmalloc(sizeof(*driver), GFP_KERNEL);
+
+       if (!driver)
+               return NULL;
+       driver->dev_priv = dev_priv;
+
+       driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
+                                             invalid_type);
+       if (!driver->default_pd)
+               goto out_err1;
+
+       spin_lock_init(&driver->lock);
+       init_rwsem(&driver->sem);
+       down_write(&driver->sem);
+       driver->register_map = registers;
+       atomic_set(&driver->needs_tlbflush, 1);
+
+       driver->has_clflush = 0;
+
+#if defined(CONFIG_X86)
+       if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
+               uint32_t tfms, misc, cap0, cap4, clflush_size;
+
+               /*
+                * clflush size is determined at kernel setup for x86_64
+                *  but not for i386. We have to do it here.
+                */
+
+               cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
+               clflush_size = ((misc >> 8) & 0xff) * 8;
+               driver->has_clflush = 1;
+               driver->clflush_add =
+                       PAGE_SIZE * clflush_size / sizeof(uint32_t);
+               driver->clflush_mask = driver->clflush_add - 1;
+               driver->clflush_mask = ~driver->clflush_mask;
+       }
+#endif
+
+       up_write(&driver->sem);
+       return driver;
+
+out_err1:
+       kfree(driver);
+       return NULL;
+}
+
+#if defined(CONFIG_X86)
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
+                              unsigned long address, uint32_t num_pages,
+                              uint32_t desired_tile_stride,
+                              uint32_t hw_tile_stride)
+{
+       struct psb_mmu_pt *pt;
+       uint32_t rows = 1;
+       uint32_t i;
+       unsigned long addr;
+       unsigned long end;
+       unsigned long next;
+       unsigned long add;
+       unsigned long row_add;
+       unsigned long clflush_add = pd->driver->clflush_add;
+       unsigned long clflush_mask = pd->driver->clflush_mask;
+
+       if (!pd->driver->has_clflush) {
+               /*ttm_tt_cache_flush(&pd->p, num_pages);*/
+               psb_pages_clflush(pd->driver, &pd->p, num_pages);
+               return;
+       }
+
+       if (hw_tile_stride)
+               rows = num_pages / desired_tile_stride;
+       else
+               desired_tile_stride = num_pages;
+
+       add = desired_tile_stride << PAGE_SHIFT;
+       row_add = hw_tile_stride << PAGE_SHIFT;
+       mb();
+       for (i = 0; i < rows; ++i) {
+
+               addr = address;
+               end = addr + add;
+
+               do {
+                       next = psb_pd_addr_end(addr, end);
+                       pt = psb_mmu_pt_map_lock(pd, addr);
+                       if (!pt)
+                               continue;
+                       do {
+                               psb_clflush(&pt->v
+                                           [psb_mmu_pt_index(addr)]);
+                       } while (addr +=
+                                        clflush_add,
+                                (addr & clflush_mask) < next);
+
+                       psb_mmu_pt_unmap_unlock(pt);
+               } while (addr = next, next != end);
+               address += row_add;
+       }
+       mb();
+}
+#else
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
+                              unsigned long address, uint32_t num_pages,
+                              uint32_t desired_tile_stride,
+                              uint32_t hw_tile_stride)
+{
+       drm_ttm_cache_flush(&pd->p, num_pages);
+}
+#endif
+
+void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+                                unsigned long address, uint32_t num_pages)
+{
+       struct psb_mmu_pt *pt;
+       unsigned long addr;
+       unsigned long end;
+       unsigned long next;
+       unsigned long f_address = address;
+
+       down_read(&pd->driver->sem);
+
+       addr = address;
+       end = addr + (num_pages << PAGE_SHIFT);
+
+       do {
+               next = psb_pd_addr_end(addr, end);
+               pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+               if (!pt)
+                       goto out;
+               do {
+                       psb_mmu_invalidate_pte(pt, addr);
+                       --pt->count;
+               } while (addr += PAGE_SIZE, addr < next);
+               psb_mmu_pt_unmap_unlock(pt);
+
+       } while (addr = next, next != end);
+
+out:
+       if (pd->hw_context != -1)
+               psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+       up_read(&pd->driver->sem);
+
+       if (pd->hw_context != -1)
+               psb_mmu_flush(pd->driver, 0);
+
+       return;
+}
+
+void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
+                         uint32_t num_pages, uint32_t desired_tile_stride,
+                         uint32_t hw_tile_stride)
+{
+       struct psb_mmu_pt *pt;
+       uint32_t rows = 1;
+       uint32_t i;
+       unsigned long addr;
+       unsigned long end;
+       unsigned long next;
+       unsigned long add;
+       unsigned long row_add;
+       unsigned long f_address = address;
+
+       if (hw_tile_stride)
+               rows = num_pages / desired_tile_stride;
+       else
+               desired_tile_stride = num_pages;
+
+       add = desired_tile_stride << PAGE_SHIFT;
+       row_add = hw_tile_stride << PAGE_SHIFT;
+
+       /* down_read(&pd->driver->sem); */
+
+       /* Make sure we only need to flush this processor's cache */
+
+       for (i = 0; i < rows; ++i) {
+
+               addr = address;
+               end = addr + add;
+
+               do {
+                       next = psb_pd_addr_end(addr, end);
+                       pt = psb_mmu_pt_map_lock(pd, addr);
+                       if (!pt)
+                               continue;
+                       do {
+                               psb_mmu_invalidate_pte(pt, addr);
+                               --pt->count;
+
+                       } while (addr += PAGE_SIZE, addr < next);
+                       psb_mmu_pt_unmap_unlock(pt);
+
+               } while (addr = next, next != end);
+               address += row_add;
+       }
+       if (pd->hw_context != -1)
+               psb_mmu_flush_ptes(pd, f_address, num_pages,
+                                  desired_tile_stride, hw_tile_stride);
+
+       /* up_read(&pd->driver->sem); */
+
+       if (pd->hw_context != -1)
+               psb_mmu_flush(pd->driver, 0);
+}
+
+int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
+                               unsigned long address, uint32_t num_pages,
+                               int type)
+{
+       struct psb_mmu_pt *pt;
+       uint32_t pte;
+       unsigned long addr;
+       unsigned long end;
+       unsigned long next;
+       unsigned long f_address = address;
+       int ret = 0;
+
+       down_read(&pd->driver->sem);
+
+       addr = address;
+       end = addr + (num_pages << PAGE_SHIFT);
+
+       do {
+               next = psb_pd_addr_end(addr, end);
+               pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+               if (!pt) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               do {
+                       pte = psb_mmu_mask_pte(start_pfn++, type);
+                       psb_mmu_set_pte(pt, addr, pte);
+                       pt->count++;
+               } while (addr += PAGE_SIZE, addr < next);
+               psb_mmu_pt_unmap_unlock(pt);
+
+       } while (addr = next, next != end);
+
+out:
+       if (pd->hw_context != -1)
+               psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+       up_read(&pd->driver->sem);
+
+       if (pd->hw_context != -1)
+               psb_mmu_flush(pd->driver, 1);
+
+       return ret;
+}
+
+int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+                        unsigned long address, uint32_t num_pages,
+                        uint32_t desired_tile_stride,
+                        uint32_t hw_tile_stride, int type)
+{
+       struct psb_mmu_pt *pt;
+       uint32_t rows = 1;
+       uint32_t i;
+       uint32_t pte;
+       unsigned long addr;
+       unsigned long end;
+       unsigned long next;
+       unsigned long add;
+       unsigned long row_add;
+       unsigned long f_address = address;
+       int ret = 0;
+
+       if (hw_tile_stride) {
+               if (num_pages % desired_tile_stride != 0)
+                       return -EINVAL;
+               rows = num_pages / desired_tile_stride;
+       } else {
+               desired_tile_stride = num_pages;
+       }
+
+       add = desired_tile_stride << PAGE_SHIFT;
+       row_add = hw_tile_stride << PAGE_SHIFT;
+
+       down_read(&pd->driver->sem);
+
+       for (i = 0; i < rows; ++i) {
+
+               addr = address;
+               end = addr + add;
+
+               do {
+                       next = psb_pd_addr_end(addr, end);
+                       pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+                       if (!pt) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       do {
+                               pte =
+                                       psb_mmu_mask_pte(page_to_pfn(*pages++),
+                                                        type);
+                               psb_mmu_set_pte(pt, addr, pte);
+                               pt->count++;
+                       } while (addr += PAGE_SIZE, addr < next);
+                       psb_mmu_pt_unmap_unlock(pt);
+
+               } while (addr = next, next != end);
+
+               address += row_add;
+       }
+out:
+       if (pd->hw_context != -1)
+               psb_mmu_flush_ptes(pd, f_address, num_pages,
+                                  desired_tile_stride, hw_tile_stride);
+
+       up_read(&pd->driver->sem);
+
+       if (pd->hw_context != -1)
+               psb_mmu_flush(pd->driver, 1);
+
+       return ret;
+}
+#if 0 /*comented out, only used in mmu test now*/
+void psb_mmu_enable_requestor(struct psb_mmu_driver *driver, uint32_t mask)
+{
+       mask &= _PSB_MMU_ER_MASK;
+       psb_iowrite32(driver,
+                     psb_ioread32(driver, PSB_CR_BIF_CTRL) & ~mask,
+                     PSB_CR_BIF_CTRL);
+       (void) psb_ioread32(driver, PSB_CR_BIF_CTRL);
+}
+
+void psb_mmu_disable_requestor(struct psb_mmu_driver *driver,
+                              uint32_t mask)
+{
+       mask &= _PSB_MMU_ER_MASK;
+       psb_iowrite32(driver, psb_ioread32(driver, PSB_CR_BIF_CTRL) | mask,
+                     PSB_CR_BIF_CTRL);
+       (void) psb_ioread32(driver, PSB_CR_BIF_CTRL);
+}
+#endif
+int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+                          unsigned long *pfn)
+{
+       int ret;
+       struct psb_mmu_pt *pt;
+       uint32_t tmp;
+       spinlock_t *lock = &pd->driver->lock;
+
+       down_read(&pd->driver->sem);
+       pt = psb_mmu_pt_map_lock(pd, virtual);
+       if (!pt) {
+               uint32_t *v;
+
+               spin_lock(lock);
+               v = kmap_atomic(pd->p, KM_USER0);
+               tmp = v[psb_mmu_pd_index(virtual)];
+               kunmap_atomic(v, KM_USER0);
+               spin_unlock(lock);
+
+               if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
+                   !(pd->invalid_pte & PSB_PTE_VALID)) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+               ret = 0;
+               *pfn = pd->invalid_pte >> PAGE_SHIFT;
+               goto out;
+       }
+       tmp = pt->v[psb_mmu_pt_index(virtual)];
+       if (!(tmp & PSB_PTE_VALID)) {
+               ret = -EINVAL;
+       } else {
+               ret = 0;
+               *pfn = tmp >> PAGE_SHIFT;
+       }
+       psb_mmu_pt_unmap_unlock(pt);
+out:
+       up_read(&pd->driver->sem);
+       return ret;
+}
+#if 0
+void psb_mmu_test(struct psb_mmu_driver *driver, uint32_t offset)
+{
+       struct page *p;
+       unsigned long pfn;
+       int ret = 0;
+       struct psb_mmu_pd *pd;
+       uint32_t *v;
+       uint32_t *vmmu;
+
+       pd = driver->default_pd;
+       if (!pd)
+               printk(KERN_WARNING "Could not get default pd\n");
+
+
+       p = alloc_page(GFP_DMA32);
+
+       if (!p) {
+               printk(KERN_WARNING "Failed allocating page\n");
+               return;
+       }
+
+       v = kmap(p);
+       memset(v, 0x67, PAGE_SIZE);
+
+       pfn = (offset >> PAGE_SHIFT);
+
+       ret = psb_mmu_insert_pages(pd, &p, pfn << PAGE_SHIFT, 1, 0, 0, 0);
+       if (ret) {
+               printk(KERN_WARNING "Failed inserting mmu page\n");
+               goto out_err1;
+       }
+
+       /* Ioremap the page through the GART aperture */
+
+       vmmu = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
+       if (!vmmu) {
+               printk(KERN_WARNING "Failed ioremapping page\n");
+               goto out_err2;
+       }
+
+       /* Read from the page with mmu disabled. */
+       printk(KERN_INFO "Page first dword is 0x%08x\n", ioread32(vmmu));
+
+       /* Enable the mmu for host accesses and read again. */
+       psb_mmu_enable_requestor(driver, _PSB_MMU_ER_HOST);
+
+       printk(KERN_INFO "MMU Page first dword is (0x67676767) 0x%08x\n",
+              ioread32(vmmu));
+       *v = 0x15243705;
+       printk(KERN_INFO "MMU Page new dword is (0x15243705) 0x%08x\n",
+              ioread32(vmmu));
+       iowrite32(0x16243355, vmmu);
+       (void) ioread32(vmmu);
+       printk(KERN_INFO "Page new dword is (0x16243355) 0x%08x\n", *v);
+
+       printk(KERN_INFO "Int stat is 0x%08x\n",
+              psb_ioread32(driver, PSB_CR_BIF_INT_STAT));
+       printk(KERN_INFO "Fault is 0x%08x\n",
+              psb_ioread32(driver, PSB_CR_BIF_FAULT));
+
+       /* Disable MMU for host accesses and clear page fault register */
+       psb_mmu_disable_requestor(driver, _PSB_MMU_ER_HOST);
+       iounmap(vmmu);
+out_err2:
+       psb_mmu_remove_pages(pd, pfn << PAGE_SHIFT, 1, 0, 0);
+out_err1:
+       kunmap(p);
+       __free_page(p);
+}
+#endif
diff --git a/drivers/staging/mrst/imgv/psb_msvdx.c b/drivers/staging/mrst/imgv/psb_msvdx.c
new file mode 100644 (file)
index 0000000..0fcc248
--- /dev/null
@@ -0,0 +1,1444 @@
+/**************************************************************************
+ * MSVDX I/O operations and IRQ handling
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm_os_linux.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include "psb_powermgmt.h"
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#ifndef list_first_entry
+#define list_first_entry(ptr, type, member) \
+       list_entry((ptr)->next, type, member)
+#endif
+
+
+static int psb_msvdx_send(struct drm_device *dev, void *cmd,
+                         unsigned long cmd_size);
+
+static int psb_msvdx_dequeue_send(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_msvdx_cmd_queue *msvdx_cmd = NULL;
+       int ret = 0;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       if (list_empty(&msvdx_priv->msvdx_queue)) {
+               PSB_DEBUG_GENERAL("MSVDXQUE: msvdx list empty.\n");
+               msvdx_priv->msvdx_busy = 0;
+               return -EINVAL;
+       }
+       msvdx_cmd = list_first_entry(&msvdx_priv->msvdx_queue,
+                                    struct psb_msvdx_cmd_queue, head);
+       PSB_DEBUG_GENERAL("MSVDXQUE: Queue has id %08x\n", msvdx_cmd->sequence);
+       ret = psb_msvdx_send(dev, msvdx_cmd->cmd, msvdx_cmd->cmd_size);
+       if (ret) {
+               DRM_ERROR("MSVDXQUE: psb_msvdx_send failed\n");
+               ret = -EINVAL;
+       }
+       list_del(&msvdx_cmd->head);
+       kfree(msvdx_cmd->cmd);
+       kfree(msvdx_cmd);
+
+       return ret;
+}
+
+static int psb_msvdx_map_command(struct drm_device *dev,
+                                struct ttm_buffer_object *cmd_buffer,
+                                unsigned long cmd_offset, unsigned long cmd_size,
+                                void **msvdx_cmd, uint32_t sequence, int copy_cmd)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       int ret = 0;
+       unsigned long cmd_page_offset = cmd_offset & ~PAGE_MASK;
+       unsigned long cmd_size_remaining;
+       struct ttm_bo_kmap_obj cmd_kmap, regio_kmap;
+       void *cmd, *cmd_copy, *cmd_start;
+       bool is_iomem;
+       int i;
+       struct HOST_BE_OPP_PARAMS * oppParam;
+       drm_psb_msvdx_frame_info_t * current_frame = NULL;
+       int first_empty = -1;
+
+
+       /* command buffers may not exceed page boundary */
+       if (cmd_size + cmd_page_offset > PAGE_SIZE)
+               return -EINVAL;
+
+       ret = ttm_bo_kmap(cmd_buffer, cmd_offset >> PAGE_SHIFT, 1, &cmd_kmap);
+       if (ret) {
+               DRM_ERROR("MSVDXQUE:ret:%d\n", ret);
+               return ret;
+       }
+
+       cmd_start = (void *)ttm_kmap_obj_virtual(&cmd_kmap, &is_iomem)
+                   + cmd_page_offset;
+       cmd = cmd_start;
+       cmd_size_remaining = cmd_size;
+
+       while (cmd_size_remaining > 0) {
+               uint32_t cur_cmd_size = MEMIO_READ_FIELD(cmd, FWRK_GENMSG_SIZE);
+               uint32_t cur_cmd_id = MEMIO_READ_FIELD(cmd, FWRK_GENMSG_ID);
+               uint32_t mmu_ptd = 0, msvdx_mmu_invalid = 0;
+               struct psb_msvdx_deblock_queue *msvdx_deblock;
+               unsigned long irq_flags;
+
+               PSB_DEBUG_GENERAL("cmd start at %08x cur_cmd_size = %d"
+                                 " cur_cmd_id = %02x fence = %08x\n",
+                                 (uint32_t) cmd, cur_cmd_size, cur_cmd_id, sequence);
+               if ((cur_cmd_size % sizeof(uint32_t))
+                   || (cur_cmd_size > cmd_size_remaining)) {
+                       ret = -EINVAL;
+                       DRM_ERROR("MSVDX: ret:%d\n", ret);
+                       goto out;
+               }
+
+               switch (cur_cmd_id) {
+               case VA_MSGID_RENDER:
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: send render message. \n");
+
+                       /* Fence ID */
+                       MEMIO_WRITE_FIELD(cmd, FW_VA_DECODE_MSG_ID, sequence);
+
+                       mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+                       msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+                                                          1, 0);
+                       if (msvdx_mmu_invalid == 1) {
+                               uint32_t flags;
+                               flags = MEMIO_READ_FIELD(cmd, FW_DEVA_DECODE_FLAGS);
+                               flags |= FW_DEVA_INVALIDATE_MMU;
+                               MEMIO_WRITE_FIELD(cmd, FW_DEVA_DECODE_FLAGS, flags);
+                               psb_gl3_global_invalidation(dev);
+
+                               PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+                       }
+
+                       /* PTD */
+                       mmu_ptd |= MEMIO_READ_FIELD(cmd,
+                                               FW_VA_DECODE_MMUPTD) & 0xff;
+                       MEMIO_WRITE_FIELD(cmd, FW_VA_DECODE_MMUPTD, mmu_ptd);
+                       break;
+
+               case VA_MSGID_OOLD:
+                       MEMIO_WRITE_FIELD(cmd, FW_DXVA_OOLD_FENCE_VALUE,
+                                         sequence);
+                       mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+                       msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+                                                          1, 0);
+                       if (msvdx_mmu_invalid == 1) {
+                               mmu_ptd |= 1;
+                               PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+                       }
+
+                       /* PTD */
+                       MEMIO_WRITE_FIELD(cmd, FW_DXVA_OOLD_MMUPTD, mmu_ptd);
+
+                       PSB_DEBUG_GENERAL("MSVDX:Get oold cmd\n");
+
+                       break;
+
+               case VA_MSGID_OOLD_MFLD:
+               case VA_MSGID_DEBLOCK_MFLD: {
+                       FW_VA_DEBLOCK_MSG * deblock_msg;
+
+                       PSB_DEBUG_GENERAL("MSVDX:Get deblock cmd for medfield\n");
+
+                       deblock_msg = (FW_VA_DEBLOCK_MSG *)cmd;
+
+                       mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+                       msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+                                                          1, 0);
+                       if (msvdx_mmu_invalid == 1) {
+                               uint32_t flags;
+                               flags = deblock_msg->flags;
+                               flags |= FW_DEVA_INVALIDATE_MMU;
+                               deblock_msg->flags = flags;
+
+                               PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+                       }
+
+
+                       deblock_msg->header.bits.msg_type = cur_cmd_id - VA_MSGID_DEBLOCK_MFLD + VA_MSGID_DEBLOCK; /* patch to right cmd type */
+                       deblock_msg->header.bits.msg_fence = (uint16_t)(sequence & 0xffff);
+                       deblock_msg->mmu_context.bits.mmu_ptd = (mmu_ptd >> 8);
+
+               }
+               break;
+
+               case VA_MSGID_DEBLOCK:
+                       msvdx_priv->deblock_enabled = 1;
+                       /* Fence ID */
+                       MEMIO_WRITE_FIELD(cmd, FW_DXVA_DEBLOCK_FENCE_VALUE,
+                                         sequence);
+                       mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+                       msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+                                                          1, 0);
+                       if (msvdx_mmu_invalid == 1) {
+                               mmu_ptd |= 1;
+                               PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+                       }
+
+                       /* PTD */
+                       MEMIO_WRITE_FIELD(cmd,
+                                         FW_DXVA_DEBLOCK_MMUPTD,
+                                         mmu_ptd);
+
+                       /* printk("Got deblock msg\n"); */
+                       /* Deblock message is followed by 32 */
+                       /* bytes of deblock params */
+                       msvdx_deblock = kmalloc(
+                                               sizeof(struct psb_msvdx_deblock_queue),
+                                               GFP_KERNEL);
+
+                       if (msvdx_deblock == NULL) {
+                               DRM_ERROR("DEBLOCK QUE: Out of memory...\n");
+                               ret =  -ENOMEM;
+                               goto out;
+                       }
+
+                       memcpy(&msvdx_deblock->dbParams, cmd + 16, sizeof(struct DEBLOCKPARAMS));
+
+                       ret = ttm_bo_kmap(
+                                     (struct ttm_buffer_object *)
+                                     msvdx_deblock->dbParams.handle,
+                                     0,
+                                     (msvdx_deblock->dbParams.buffer_size +
+                                      PAGE_SIZE - 1) >> PAGE_SHIFT,
+                                     &regio_kmap);
+
+                       /* printk("deblock regio buffer size is 0x%x\n",
+                          msvdx_deblock->dbParams.buffer_size); */
+
+                       if (likely(!ret)) {
+                               msvdx_deblock->dbParams.pPicparams = kmalloc(
+                                               msvdx_deblock->dbParams.buffer_size,
+                                               GFP_KERNEL);
+
+                               if (msvdx_deblock->dbParams.pPicparams != NULL)
+                                       memcpy(
+                                               msvdx_deblock->dbParams.pPicparams,
+                                               regio_kmap.virtual,
+                                               msvdx_deblock->dbParams.buffer_size);
+                               ttm_bo_kunmap(&regio_kmap);
+                       }
+                       spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+                       list_add_tail(&msvdx_deblock->head,
+                                     &msvdx_priv->deblock_queue);
+                       spin_unlock_irqrestore(&msvdx_priv->msvdx_lock,
+                                              irq_flags);
+
+                       cmd += sizeof(struct DEBLOCKPARAMS);
+                       cmd_size_remaining -= sizeof(struct DEBLOCKPARAMS);
+                       break;
+
+               case VA_MSGID_HOST_BE_OPP:
+
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: send host_be_opp message. \n");
+
+                       msvdx_priv->host_be_opp_enabled = 1;
+                       /* Fence ID */
+                       MEMIO_WRITE_FIELD(cmd, FW_VA_HOST_BE_OPP_FENCE_VALUE,
+                                         sequence);
+                       mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+                       msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+                                                          1, 0);
+                       if (msvdx_mmu_invalid == 1) {
+                               mmu_ptd |= 1;
+                               PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+                       }
+
+                       /* PTD */
+                       MEMIO_WRITE_FIELD(cmd,
+                                         FW_VA_HOST_BE_OPP_MMUPTD,
+                                         mmu_ptd);
+
+                       /* HostBeOpp message is followed by 32 bytes of host_be_opp params */
+                       oppParam = kmalloc(
+                                          sizeof(struct HOST_BE_OPP_PARAMS),
+                                          GFP_KERNEL);
+
+                       if (oppParam == NULL) {
+                               DRM_ERROR("DEBLOCK QUE: Out of memory...\n");
+                               ret =  -ENOMEM;
+                               goto out;
+                       }
+
+                       memcpy(oppParam, cmd + 16, sizeof(struct HOST_BE_OPP_PARAMS));
+                       /*get the right frame_info struct for current surface*/
+                       for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+                               if (msvdx_priv->frame_info[i].handle == oppParam->handle) {
+                                       current_frame = &(msvdx_priv->frame_info[i]);
+                                       break;
+                               }
+                               if ((first_empty == -1) && (msvdx_priv->frame_info[i].handle  == 0))
+                                       first_empty = i;
+                       }
+
+                       /*if didn't find the struct for current surface, use the earliest empty one*/
+                       if (!current_frame) {
+                               if (first_empty == -1) {
+                                       DRM_ERROR("failed find the struct for current surface and also there is no empty one.\n");
+                                       ret = -EFAULT;
+                                       goto out;
+                               }
+                               current_frame = &(msvdx_priv->frame_info[first_empty]);
+                       }
+
+                       memset(current_frame, 0, sizeof(drm_psb_msvdx_frame_info_t));
+                       current_frame->handle = oppParam->handle;
+                       current_frame->buffer_stride = oppParam->buffer_stride;
+                       current_frame->buffer_size = oppParam->buffer_size;
+                       current_frame->picture_width_mb = oppParam->picture_width_mb;
+                       current_frame->size_mb = oppParam->size_mb;
+                       current_frame->fence = sequence;
+
+
+                       cmd += sizeof(struct HOST_BE_OPP_PARAMS);
+                       cmd_size_remaining -= sizeof(struct HOST_BE_OPP_PARAMS);
+
+                       break;
+
+               default:
+                       /* Msg not supported */
+                       ret = -EINVAL;
+                       PSB_DEBUG_GENERAL("MSVDX: ret:%d\n", ret);
+                       goto out;
+               }
+
+               cmd += cur_cmd_size;
+               cmd_size_remaining -= cur_cmd_size;
+       }
+
+       if (copy_cmd) {
+               PSB_DEBUG_GENERAL("MSVDXQUE:copying command\n");
+
+               cmd_copy = kzalloc(cmd_size, GFP_KERNEL);
+               if (cmd_copy == NULL) {
+                       ret = -ENOMEM;
+                       DRM_ERROR("MSVDX: fail to callc,ret=:%d\n", ret);
+                       goto out;
+               }
+               memcpy(cmd_copy, cmd_start, cmd_size);
+               *msvdx_cmd = cmd_copy;
+       } else {
+               PSB_DEBUG_GENERAL("MSVDXQUE:did NOT copy command\n");
+               ret = psb_msvdx_send(dev, cmd_start, cmd_size);
+               if (ret) {
+                       DRM_ERROR("MSVDXQUE: psb_msvdx_send failed\n");
+                       ret = -EINVAL;
+               }
+       }
+
+out:
+       ttm_bo_kunmap(&cmd_kmap);
+
+       return ret;
+}
+
+static int psb_submit_video_cmdbuf(struct drm_device *dev,
+                           struct ttm_buffer_object *cmd_buffer,
+                           unsigned long cmd_offset, unsigned long cmd_size,
+                           struct ttm_fence_object *fence)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t sequence =  dev_priv->sequence[PSB_ENGINE_VIDEO];
+       unsigned long irq_flags;
+       int ret = 0;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       int offset = 0;
+       /* psb_schedule_watchdog(dev_priv); */
+
+       spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+
+       /* expected msvdx_needs_reset is set after previous session exited
+        * but msvdx_hw_busy is always 1, and caused powerdown not excuted
+        * so reload the firmware for every new context
+        */
+       dev_priv->last_msvdx_ctx = dev_priv->msvdx_ctx;
+
+       if (msvdx_priv->msvdx_needs_reset) {
+               spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+               PSB_DEBUG_GENERAL("MSVDX: will reset msvdx\n");
+               if (psb_msvdx_reset(dev_priv)) {
+                       ret = -EBUSY;
+                       DRM_ERROR("MSVDX: Reset failed\n");
+                       return ret;
+               }
+               msvdx_priv->msvdx_needs_reset = 0;
+               msvdx_priv->msvdx_busy = 0;
+
+               psb_msvdx_init(dev);
+
+               /* restore vec local mem if needed */
+               if (msvdx_priv->vec_local_mem_saved) {
+                       for (offset = 0; offset < VEC_LOCAL_MEM_BYTE_SIZE / 4; ++offset)
+                               PSB_WMSVDX32(msvdx_priv->vec_local_mem_data[offset],
+                                            VEC_LOCAL_MEM_OFFSET + offset * 4);
+
+                       msvdx_priv->vec_local_mem_saved = 0;
+               }
+
+               spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+       }
+
+       if (!msvdx_priv->msvdx_fw_loaded) {
+               spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+               PSB_DEBUG_GENERAL("MSVDX:reload FW to MTX\n");
+
+               ret = psb_setup_fw(dev);
+               if (ret) {
+                       DRM_ERROR("MSVDX:fail to load FW\n");
+                       /* FIXME: find a proper return value */
+                       return -EFAULT;
+               }
+               msvdx_priv->msvdx_fw_loaded = 1;
+
+               PSB_DEBUG_GENERAL("MSVDX: load firmware successfully\n");
+               spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+       }
+
+       if (!msvdx_priv->msvdx_busy) {
+               msvdx_priv->msvdx_busy = 1;
+               spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+               PSB_DEBUG_GENERAL("MSVDX: commit command to HW,seq=0x%08x\n",
+                                 sequence);
+               ret = psb_msvdx_map_command(dev, cmd_buffer, cmd_offset,
+                                           cmd_size, NULL, sequence, 0);
+               if (ret) {
+                       DRM_ERROR("MSVDXQUE: Failed to extract cmd\n");
+                       return ret;
+               }
+       } else {
+               struct psb_msvdx_cmd_queue *msvdx_cmd;
+               void *cmd = NULL;
+
+               spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+               /* queue the command to be sent when the h/w is ready */
+               PSB_DEBUG_GENERAL("MSVDXQUE: queueing sequence:%08x..\n",
+                                 sequence);
+               msvdx_cmd = kzalloc(sizeof(struct psb_msvdx_cmd_queue),
+                                   GFP_KERNEL);
+               if (msvdx_cmd == NULL) {
+                       DRM_ERROR("MSVDXQUE: Out of memory...\n");
+                       return -ENOMEM;
+               }
+
+               ret = psb_msvdx_map_command(dev, cmd_buffer, cmd_offset,
+                                           cmd_size, &cmd, sequence, 1);
+               if (ret) {
+                       DRM_ERROR("MSVDXQUE: Failed to extract cmd\n");
+                       kfree(msvdx_cmd
+                            );
+                       return ret;
+               }
+               msvdx_cmd->cmd = cmd;
+               msvdx_cmd->cmd_size = cmd_size;
+               msvdx_cmd->sequence = sequence;
+               spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+               list_add_tail(&msvdx_cmd->head, &msvdx_priv->msvdx_queue);
+               if (!msvdx_priv->msvdx_busy) {
+                       msvdx_priv->msvdx_busy = 1;
+                       PSB_DEBUG_GENERAL("MSVDXQUE: Need immediate dequeue\n");
+                       psb_msvdx_dequeue_send(dev);
+               }
+               spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+       }
+
+       return ret;
+}
+
+int psb_cmdbuf_video(struct drm_file *priv,
+                    struct list_head *validate_list,
+                    uint32_t fence_type,
+                    struct drm_psb_cmdbuf_arg *arg,
+                    struct ttm_buffer_object *cmd_buffer,
+                    struct psb_ttm_fence_rep *fence_arg)
+{
+       struct drm_device *dev = priv->minor->dev;
+       struct ttm_fence_object *fence;
+       int ret;
+
+       /*
+        * Check this. Doesn't seem right. Have fencing done AFTER command
+        * submission and make sure drm_psb_idle idles the MSVDX completely.
+        */
+       ret =
+               psb_submit_video_cmdbuf(dev, cmd_buffer, arg->cmdbuf_offset,
+                                       arg->cmdbuf_size, NULL);
+       if (ret)
+               return ret;
+
+
+       /* DRM_ERROR("Intel: Fix video fencing!!\n"); */
+       psb_fence_or_sync(priv, PSB_ENGINE_VIDEO, fence_type,
+                         arg->fence_flags, validate_list, fence_arg,
+                         &fence);
+
+       ttm_fence_object_unref(&fence);
+       spin_lock(&cmd_buffer->bdev->fence_lock);
+       if (cmd_buffer->sync_obj != NULL)
+               ttm_fence_sync_obj_unref(&cmd_buffer->sync_obj);
+       spin_unlock(&cmd_buffer->bdev->fence_lock);
+
+       return 0;
+}
+
+
+static int psb_msvdx_send(struct drm_device *dev, void *cmd,
+                         unsigned long cmd_size)
+{
+       int ret = 0;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       while (cmd_size > 0) {
+               uint32_t cur_cmd_size = MEMIO_READ_FIELD(cmd, FWRK_GENMSG_SIZE);
+               uint32_t cur_cmd_id = MEMIO_READ_FIELD(cmd, FWRK_GENMSG_ID);
+               if (cur_cmd_size > cmd_size) {
+                       ret = -EINVAL;
+                       DRM_ERROR("MSVDX:cmd_size %lu cur_cmd_size %lu\n",
+                                 cmd_size, (unsigned long)cur_cmd_size);
+                       goto out;
+               }
+
+               /* Send the message to h/w */
+               ret = psb_mtx_send(dev_priv, cmd);
+               if (ret) {
+                       PSB_DEBUG_GENERAL("MSVDX: ret:%d\n", ret);
+                       goto out;
+               }
+               cmd += cur_cmd_size;
+               cmd_size -= cur_cmd_size;
+               if (cur_cmd_id == VA_MSGID_HOST_BE_OPP) {
+                       cmd += sizeof(struct HOST_BE_OPP_PARAMS);
+                       cmd_size -= sizeof(struct HOST_BE_OPP_PARAMS);
+               }
+               if (cmd_size)
+                       PSB_UDELAY(200);
+       }
+
+out:
+       PSB_DEBUG_GENERAL("MSVDX: ret:%d\n", ret);
+       return ret;
+}
+
+int psb_mtx_send(struct drm_psb_private *dev_priv, const void *msg)
+{
+       static uint32_t pad_msg[FWRK_PADMSG_SIZE];
+       const uint32_t *p_msg = (uint32_t *) msg;
+       uint32_t msg_num, words_free, ridx, widx, buf_size, buf_offset;
+       int ret = 0;
+
+       PSB_DEBUG_GENERAL("MSVDX: psb_mtx_send\n");
+
+       /* we need clocks enabled before we touch VEC local ram */
+       PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+       msg_num = (MEMIO_READ_FIELD(msg, FWRK_GENMSG_SIZE) + 3) / 4;
+
+       /*
+               {
+                       int i;
+                       printk("MSVDX: psb_mtx_send is %dDW\n", msg_num);
+
+                       for(i = 0; i < msg_num; i++)
+                               printk("0x%08x ", p_msg[i]);
+                       printk("\n");
+               }
+       */
+       buf_size = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_BUF_SIZE) & ((1 << 16) - 1);
+
+       if (msg_num > buf_size) {
+               ret = -EINVAL;
+               DRM_ERROR("MSVDX: message exceed maximum,ret:%d\n", ret);
+               goto out;
+       }
+
+       ridx = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_RD_INDEX);
+       widx = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_WRT_INDEX);
+
+
+       buf_size = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_BUF_SIZE) & ((1 << 16) - 1);
+       /*0x2000 is VEC Local Ram offset*/
+       buf_offset =
+               (PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_BUF_SIZE) >> 16) + 0x2000;
+
+       /* message would wrap, need to send a pad message */
+       if (widx + msg_num > buf_size) {
+               /* Shouldn't happen for a PAD message itself */
+               BUG_ON(MEMIO_READ_FIELD(msg, FWRK_GENMSG_ID)
+                      == FWRK_MSGID_PADDING);
+
+               /* if the read pointer is at zero then we must wait for it to
+                * change otherwise the write pointer will equal the read
+                * pointer,which should only happen when the buffer is empty
+                *
+                * This will only happens if we try to overfill the queue,
+                * queue management should make
+                * sure this never happens in the first place.
+                */
+               BUG_ON(0 == ridx);
+               if (0 == ridx) {
+                       ret = -EINVAL;
+                       DRM_ERROR("MSVDX: RIndex=0, ret:%d\n", ret);
+                       goto out;
+               }
+
+               /* Send a pad message */
+               MEMIO_WRITE_FIELD(pad_msg, FWRK_GENMSG_SIZE,
+                                 (buf_size - widx) << 2);
+               MEMIO_WRITE_FIELD(pad_msg, FWRK_GENMSG_ID,
+                                 FWRK_MSGID_PADDING);
+               psb_mtx_send(dev_priv, pad_msg);
+               widx = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_WRT_INDEX);
+       }
+
+       if (widx >= ridx)
+               words_free = buf_size - (widx - ridx) - 1;
+       else
+               words_free = ridx - widx - 1;
+
+       BUG_ON(msg_num > words_free);
+       if (msg_num > words_free) {
+               ret = -EINVAL;
+               DRM_ERROR("MSVDX: msg_num > words_free, ret:%d\n", ret);
+               goto out;
+       }
+       while (msg_num > 0) {
+               PSB_WMSVDX32(*p_msg++, buf_offset + (widx << 2));
+               msg_num--;
+               widx++;
+               if (buf_size == widx)
+                       widx = 0;
+       }
+
+       PSB_WMSVDX32(widx, MSVDX_COMMS_TO_MTX_WRT_INDEX);
+
+       /* Make sure clocks are enabled before we kick */
+       PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+       PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+       /* signal an interrupt to let the mtx know there is a new message */
+       /* PSB_WMSVDX32(1, MSVDX_MTX_KICKI); */
+       PSB_WMSVDX32(1, MSVDX_MTX_KICK);
+
+       /* Read MSVDX Register several times in case Idle signal assert */
+       PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+       PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+       PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+       PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+
+
+out:
+       return ret;
+}
+
+static int psb_msvdx_towpass_deblock(struct drm_device *dev,
+                                    uint32_t *pPicparams)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       uint32_t cmd_size, cmd_count = 0;
+       uint32_t cmd_id, reg, value, wait, reg_value, read = 0, ret = 0;
+
+       cmd_size = *pPicparams++;
+       PSB_DEBUG_GENERAL("MSVDX DEBLOCK: deblock get cmd size %d\n", cmd_size);
+       /* printk("MSVDX DEBLOCK: deblock get cmd size %d\n", cmd_size); */
+
+       do {
+               cmd_id = (*pPicparams) & 0xf0000000;
+               reg = (*pPicparams++)  & 0x0fffffff;
+               switch (cmd_id) {
+               case MSVDX_DEBLOCK_REG_SET: {
+                       value = *pPicparams++;
+                       PSB_WMSVDX32(value, reg);
+                       cmd_count += 2;
+                       break;
+               }
+               case MSVDX_DEBLOCK_REG_GET: {
+                       read = PSB_RMSVDX32(reg);
+                       cmd_count += 1;
+                       break;
+               }
+               case MSVDX_DEBLOCK_REG_POLLn: {
+                       value = *pPicparams++;
+                       wait = 0;
+
+                       do {
+                               reg_value = PSB_RMSVDX32(reg);
+                       } while ((wait++ < 20000) && (value > reg_value));
+
+                       if (wait >= 20000) {
+                               ret = 1;
+                               PSB_DEBUG_GENERAL(
+                                       "MSVDX DEBLOCK: polln cmd space time out!\n");
+                               goto finish_deblock;
+                       }
+                       cmd_count += 2;
+                       break;
+               }
+               case MSVDX_DEBLOCK_REG_POLLx: {
+                       wait = 0;
+
+                       do {
+                               reg_value = PSB_RMSVDX32(reg);
+                       } while ((wait++ < 20000) && (read > reg_value));
+
+                       if (wait >= 20000) {
+                               ret = 1;
+                               PSB_DEBUG_GENERAL(
+                                       "MSVDX DEBLOCK: pollx cmd space time out!\n");
+                               goto finish_deblock;
+                       }
+
+                       cmd_count += 1;
+                       break;
+               }
+               default:
+                       ret = 1;
+                       PSB_DEBUG_GENERAL(
+                               "MSVDX DEBLOCK: get error cmd_id: 0x%x!\n",
+                               cmd_id);
+                       PSB_DEBUG_GENERAL(
+                               "MSVDX DEBLOCK: execute cmd num is %d\n",
+                               cmd_count);
+                       /* printk("MSVDX DEBLOCK: get error cmd_id: 0x%x!\n",
+                          cmd_id); */
+                       /* printk("MSVDX DEBLOCK: execute cmd num is %d\n",
+                          cmd_count); */
+                       goto finish_deblock;
+               }
+       } while (cmd_count < cmd_size);
+
+
+finish_deblock:
+       PSB_DEBUG_GENERAL("MSVDX DEBLOCK: execute cmd num is %d\n", cmd_count);
+       return ret;
+}
+
+/*
+ * MSVDX MTX interrupt
+ */
+static void psb_msvdx_mtx_interrupt(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       static uint32_t buf[128]; /* message buffer */
+       uint32_t ridx, widx, buf_size, buf_offset;
+       uint32_t num, ofs; /* message num and offset */
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       int i;
+
+       PSB_DEBUG_GENERAL("MSVDX:Got a MSVDX MTX interrupt\n");
+
+       /* Are clocks enabled  - If not enable before
+        * attempting to read from VLR
+        */
+       if (PSB_RMSVDX32(MSVDX_MAN_CLK_ENABLE) != (clk_enable_all)) {
+               PSB_DEBUG_GENERAL("MSVDX:Clocks disabled when Interupt set\n");
+               PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+       }
+
+loop: /* just for coding style check */
+       ridx = PSB_RMSVDX32(MSVDX_COMMS_TO_HOST_RD_INDEX);
+       widx = PSB_RMSVDX32(MSVDX_COMMS_TO_HOST_WRT_INDEX);
+
+       /* Get out of here if nothing */
+       if (ridx == widx)
+               goto done;
+
+       buf_size = PSB_RMSVDX32(MSVDX_COMMS_TO_HOST_BUF_SIZE) & ((1 << 16) - 1);
+       /*0x2000 is VEC Local Ram offset*/
+       buf_offset =
+               (PSB_RMSVDX32(MSVDX_COMMS_TO_HOST_BUF_SIZE) >> 16) + 0x2000;
+
+       ofs = 0;
+       buf[ofs] = PSB_RMSVDX32(buf_offset + (ridx << 2));
+
+       /* round to nearest word */
+       num = (MEMIO_READ_FIELD(buf, FWRK_GENMSG_SIZE) + 3) / 4;
+
+       /* ASSERT(num <= sizeof(buf) / sizeof(uint32_t)); */
+
+       if (++ridx >= buf_size)
+               ridx = 0;
+
+       for (ofs++; ofs < num; ofs++) {
+               buf[ofs] = PSB_RMSVDX32(buf_offset + (ridx << 2));
+
+               if (++ridx >= buf_size)
+                       ridx = 0;
+       }
+
+       /* Update the Read index */
+       PSB_WMSVDX32(ridx, MSVDX_COMMS_TO_HOST_RD_INDEX);
+
+       if (msvdx_priv->msvdx_needs_reset)
+               goto loop;
+
+       switch (MEMIO_READ_FIELD(buf, FWRK_GENMSG_ID)) {
+       case VA_MSGID_CMD_HW_PANIC:
+       case VA_MSGID_CMD_FAILED: {
+               /* For VXD385 firmware, fence value is not validate here */
+               uint32_t msg_id = MEMIO_READ_FIELD(buf, FWRK_GENMSG_ID);
+               uint32_t diff = 0;
+               uint32_t fence, fault;
+               uint32_t last_mb, first_mb;
+               drm_psb_msvdx_frame_info_t *failed_frame = NULL;
+
+               if (msg_id == VA_MSGID_CMD_HW_PANIC)
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: get panic message.\n");
+               else
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: get failed message.\n");
+
+               if (msg_id == VA_MSGID_CMD_HW_PANIC) {
+                       fence = MEMIO_READ_FIELD(buf,
+                                                FW_VA_HW_PANIC_FENCE_VALUE);
+                       first_mb = MEMIO_READ_FIELD(buf,
+                                                   FW_VA_HW_PANIC_FIRST_MB_NUM);
+                       last_mb = MEMIO_READ_FIELD(buf,
+                                                  FW_VA_HW_PANIC_FAULT_MB_NUM);
+                       printk("jiangfei debug: fence in panic message is %d.\n", fence);
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE fence is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FENCE_VALUE));
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE first mb num is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FIRST_MB_NUM));
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE fault mb num is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FAULT_MB_NUM));
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE fe status is 0x%x.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FESTATUS));
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE be status is 0x%x.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_BESTATUS));
+               } else {
+                       fence = MEMIO_READ_FIELD(buf,
+                                                FW_VA_CMD_FAILED_FENCE_VALUE);
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: FAILED MESSAGE fence is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FIRST_MB_NUM));
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: FAILED MESSAGE flag is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_CMD_FAILED_FLAGS));
+               }
+
+               fence = MEMIO_READ_FIELD(buf, FW_DEVA_CMD_FAILED_MSG_ID);
+               fault = MEMIO_READ_FIELD(buf, FW_DEVA_CMD_FAILED_FLAGS);
+
+               if (msg_id == VA_MSGID_CMD_HW_PANIC)
+                       PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_CMD_HW_PANIC:"
+                                         "Fault detected"
+                                         " - Fence: %08x"
+                                         " - resetting and ignoring error\n",
+                                         fence);
+               else
+                       PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_CMD_FAILED:"
+                                         "Fault detected"
+                                         " - Fence: %08x"
+                                         " - resetting and ignoring error\n",
+                                         fence);
+
+               msvdx_priv->msvdx_needs_reset = 1;
+
+               if (msg_id == VA_MSGID_CMD_HW_PANIC) {
+                       diff = msvdx_priv->msvdx_current_sequence
+                              - dev_priv->sequence[PSB_ENGINE_VIDEO];
+
+                       if (diff > 0x0FFFFFFF)
+                               msvdx_priv->msvdx_current_sequence++;
+
+                       PSB_DEBUG_GENERAL("MSVDX: Fence ID missing, "
+                                         "assuming %08x\n",
+                                         msvdx_priv->msvdx_current_sequence);
+               } else {
+                       msvdx_priv->msvdx_current_sequence = fence;
+               }
+
+               psb_fence_error(dev, PSB_ENGINE_VIDEO,
+                               msvdx_priv->msvdx_current_sequence,
+                               _PSB_FENCE_TYPE_EXE, DRM_CMD_FAILED);
+
+               /* Flush the command queue */
+               psb_msvdx_flush_cmd_queue(dev);
+
+               if (msvdx_priv->host_be_opp_enabled) {
+                       /*get the frame_info struct for error concealment frame*/
+                       for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+                               /*by default the fence is 0, so there is problem here???*/
+                               if (msvdx_priv->frame_info[i].fence == fence) {
+                                       failed_frame = &msvdx_priv->frame_info[i];
+                                       break;
+                               }
+                       }
+                       if (!failed_frame) {
+                               DRM_ERROR("MSVDX: didn't find frame_info which matched the fence %d in failed/panic message\n", fence);
+                               goto done;
+                       }
+
+                       failed_frame->fw_status = 1; /* set ERROR flag */
+               } else
+                       msvdx_priv->fw_status = 1; /* set ERROR flag */
+
+               goto done;
+       }
+       case VA_MSGID_CMD_COMPLETED: {
+               uint32_t fence;
+               uint32_t flags = MEMIO_READ_FIELD(buf, FW_VA_CMD_COMPLETED_FLAGS);
+               /* uint32_t last_mb = MEMIO_READ_FIELD(buf,
+                  FW_VA_CMD_COMPLETED_LASTMB);
+               */
+
+               fence = MEMIO_READ_FIELD(buf, FW_VA_CMD_COMPLETED_MSG_ID);
+
+               PSB_DEBUG_GENERAL("MSVDX:VA_MSGID_CMD_COMPLETED: "
+                                 "FenceID: %08x, flags: 0x%x\n",
+                                 fence, flags);
+
+               msvdx_priv->msvdx_current_sequence = fence;
+               msvdx_priv->ref_pic_fence = fence;
+
+               psb_fence_handler(dev, PSB_ENGINE_VIDEO);
+
+               if (flags & FW_VA_RENDER_HOST_INT) {
+                       /*Now send the next command from the msvdx cmd queue */
+                       psb_msvdx_dequeue_send(dev);
+                       goto done;
+               }
+
+               break;
+       }
+       case VA_MSGID_CMD_COMPLETED_BATCH: {
+               uint32_t fence = MEMIO_READ_FIELD(buf,
+                                                 FW_VA_CMD_COMPLETED_FENCE_VALUE);
+               uint32_t tickcnt = MEMIO_READ_FIELD(buf,
+                                                   FW_VA_CMD_COMPLETED_NO_TICKS);
+               (void)tickcnt;
+               /* we have the fence value in the message */
+               PSB_DEBUG_GENERAL("MSVDX:VA_MSGID_CMD_COMPLETED_BATCH:"
+                                 " FenceID: %08x, TickCount: %08x\n",
+                                 fence, tickcnt);
+               msvdx_priv->msvdx_current_sequence = fence;
+
+               break;
+       }
+       case VA_MSGID_ACK:
+               PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_ACK\n");
+               break;
+
+       case VA_MSGID_TEST1:
+               PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_TEST1\n");
+               break;
+
+               /* Penwell deblock is not implemented here */
+       case VA_MSGID_DEBLOCK_REQUIRED: {
+               uint32_t ctxid = MEMIO_READ_FIELD(buf,
+                                                 FW_VA_DEBLOCK_REQUIRED_CONTEXT);
+               struct psb_msvdx_deblock_queue *msvdx_deblock;
+               uint32_t fence = MEMIO_READ_FIELD(buf,
+                                                 FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE);
+
+               PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_DEBLOCK_REQUIRED"
+                                 " Context=%08x\n", ctxid);
+
+
+               /*deblock and on-be-opp use the same message, there is difficulty to distinguish them*/
+               /*now I just let user space use cpu copy error mb*/
+               if ((msvdx_priv->deblock_enabled == 1) && (msvdx_priv->host_be_opp_enabled == 1)) {
+                       DRM_ERROR("MSVDX: should not support both deblock and host_be_opp message. \n");
+                       goto done;
+               } else if (msvdx_priv->deblock_enabled == 1) {
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: get deblock required message for deblock operation.\n");
+                       if (list_empty(&msvdx_priv->deblock_queue)) {
+                               PSB_DEBUG_GENERAL(
+                                       "DEBLOCKQUE: deblock param list is empty\n");
+                               PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+                               PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+                               goto done;
+                       }
+                       msvdx_deblock = list_first_entry(&msvdx_priv->deblock_queue,
+                                                        struct psb_msvdx_deblock_queue, head);
+
+                       if (0) {
+                               PSB_DEBUG_GENERAL("MSVDX DEBLOCK: by pass \n");
+                               /* try to unblock rendec */
+                               PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+                               PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+                               kfree(msvdx_deblock->dbParams.pPicparams);
+                               list_del(&msvdx_deblock->head);
+                               goto done;
+                       }
+
+
+                       if (ctxid != msvdx_deblock->dbParams.ctxid) {
+                               PSB_DEBUG_GENERAL("MSVDX DEBLOCK: wrong ctxid, may "
+                                                 "caused by multiple context since "
+                                                 "it's not supported yet\n");
+                               /* try to unblock rendec */
+                               PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+                               PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+                               kfree(msvdx_deblock->dbParams.pPicparams);
+                               list_del(&msvdx_deblock->head);
+                               goto done;
+                       }
+
+                       if (msvdx_deblock->dbParams.pPicparams) {
+                               PSB_DEBUG_GENERAL("MSVDX DEBLOCK: start deblocking\n");
+                               /* printk("MSVDX DEBLOCK: start deblocking\n"); */
+
+                               if (psb_msvdx_towpass_deblock(dev,
+                                                             msvdx_deblock->dbParams.pPicparams)) {
+
+                                       PSB_DEBUG_GENERAL(
+                                               "MSVDX DEBLOCK: deblock fail!\n");
+                                       PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+                                       PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+                               }
+                               kfree(msvdx_deblock->dbParams.pPicparams);
+                       } else {
+                               PSB_DEBUG_GENERAL("MSVDX DEBLOCK: deblock abort!\n");
+                               /* printk("MSVDX DEBLOCK: deblock abort!\n"); */
+                               PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+                               PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+                       }
+
+                       list_del(&msvdx_deblock->head);
+                       kfree(msvdx_deblock);
+               } else if (msvdx_priv->host_be_opp_enabled == 1) {
+                       PSB_DEBUG_MSVDX("MSVDX_DEBUG: get deblock required message for error concealment.\n");
+
+                       /* try to unblock rendec */
+                       PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+                       PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+
+                       /*do error concealment with hw*/
+                       msvdx_priv->ec_fence = fence;
+                       schedule_work(&msvdx_priv->ec_work);
+               }
+
+               break;
+       }
+
+       case VA_MSGID_CMD_CONTIGUITY_WARNING: {
+               drm_psb_msvdx_frame_info_t *ec_frame = NULL;
+               drm_psb_msvdx_decode_status_t *fault_region = NULL;
+
+               /*get erro info*/
+               uint32_t fence = MEMIO_READ_FIELD(buf,
+                                                 FW_VA_CONTIGUITY_WARNING_FENCE_VALUE);
+               uint32_t ui32Start = MEMIO_READ_FIELD(buf,
+                                                     FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM);
+               uint32_t ui32End = MEMIO_READ_FIELD(buf,
+                                                   FW_VA_CONTIGUITY_WARNING_END_MB_NUM);
+               PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_CMD_CONTIGUITY_WARNING\n");
+               PSB_DEBUG_MSVDX("MSVDX_DEBUG: get contiguity warning message.\n");
+               PSB_DEBUG_MSVDX("MSVDX_DEBUG: CONTIGUITY_WARNING MESSAGE fence is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_CONTIGUITY_WARNING_FENCE_VALUE));
+               PSB_DEBUG_MSVDX("MSVDX_DEBUG: CONTIGUITY_WARNING MESSAGE end mb num is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_CONTIGUITY_WARNING_END_MB_NUM));
+               PSB_DEBUG_MSVDX("MSVDX_DEBUG: CONTIGUITY_WARNING MESSAGE begin mb num is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM));
+
+               /*get the frame_info struct for error concealment frame*/
+               for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+                       if (msvdx_priv->frame_info[i].fence == fence) {
+                               ec_frame = &msvdx_priv->frame_info[i];
+                               break;
+                       }
+               }
+               if (!ec_frame) {
+                       DRM_ERROR("MSVDX: didn't find frame_info which matched the fence %d when get contiguity warning.\n", fence);
+                       goto done;
+               } else if (msvdx_priv->host_be_opp_enabled) {
+                       ec_frame->fw_status = 1;
+                       fault_region = &ec_frame->decode_status;
+                       if (ui32Start == 0xffff) {
+                               if (fault_region->num_error_slice == 0) {
+                                       fault_region->start_error_mb_list[fault_region->num_error_slice] = 0;
+                                       fault_region->end_error_mb_list[fault_region->num_error_slice] = ui32End;
+                                       fault_region->num_error_slice++;
+                               } else if (fault_region->end_error_mb_list[fault_region->num_error_slice - 1] == 0xffff) {
+                                       fault_region->end_error_mb_list[fault_region->num_error_slice - 1] = ui32End;
+                               }
+                       } else if (ui32Start <  ui32End) {
+                               fault_region->start_error_mb_list[fault_region->num_error_slice] = ui32Start;
+                               fault_region->end_error_mb_list[fault_region->num_error_slice] = ui32End;
+                               fault_region->num_error_slice++;
+                       } else {
+                               DRM_ERROR("msvdx error: start mb counter should not be larger than end mb counter.\n");
+                               goto done;
+                       }
+               }
+
+               break;
+
+       }
+       default:
+               DRM_ERROR("ERROR: msvdx Unknown message from MTX, ID:0x%08x\n", MEMIO_READ_FIELD(buf, FWRK_GENMSG_ID));
+               goto done;
+       }
+
+done:
+       if (ridx != widx) {
+               PSB_DEBUG_GENERAL("MSVDX Interrupt: there are more message to be read\n");
+               goto loop;
+       }
+       /* we get a frame/slice done, try to save some power*/
+       if (drm_msvdx_pmpolicy != PSB_PMPOLICY_NOPM)
+               schedule_delayed_work(&dev_priv->scheduler.msvdx_suspend_wq, 0);
+
+       DRM_MEMORYBARRIER();    /* TBD check this... */
+}
+
+
+/*
+ * MSVDX interrupt.
+ */
+IMG_BOOL psb_msvdx_interrupt(IMG_VOID *pvData)
+{
+       struct drm_device *dev;
+       struct drm_psb_private *dev_priv;
+       struct msvdx_private *msvdx_priv;
+       uint32_t msvdx_stat;
+
+       if (pvData == IMG_NULL) {
+               DRM_ERROR("ERROR: msvdx %s, Invalid params\n", __func__);
+               return IMG_FALSE;
+       }
+
+       dev = (struct drm_device *)pvData;
+
+       dev_priv = (struct drm_psb_private *) dev->dev_private;
+       msvdx_priv = dev_priv->msvdx_private;
+
+       msvdx_priv->msvdx_hw_busy = REG_READ(0x20D0) & (0x1 << 9);
+
+       msvdx_stat = PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+
+       if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK) {
+               /*Ideally we should we should never get to this */
+               PSB_DEBUG_IRQ("MSVDX:MMU Fault:0x%x\n", msvdx_stat);
+
+               /* Pause MMU */
+               PSB_WMSVDX32(MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK,
+                            MSVDX_MMU_CONTROL0);
+               DRM_WRITEMEMORYBARRIER();
+
+               /* Clear this interupt bit only */
+               PSB_WMSVDX32(MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK,
+                            MSVDX_INTERRUPT_CLEAR);
+               PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
+               DRM_READMEMORYBARRIER();
+
+               msvdx_priv->msvdx_needs_reset = 1;
+       } else if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK) {
+               PSB_DEBUG_IRQ
+               ("MSVDX: msvdx_stat: 0x%x(MTX)\n", msvdx_stat);
+
+               /* Clear all interupt bits */
+               PSB_WMSVDX32(0xffff, MSVDX_INTERRUPT_CLEAR);
+               PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
+               DRM_READMEMORYBARRIER();
+
+               psb_msvdx_mtx_interrupt(dev);
+       }
+
+       return IMG_TRUE;
+}
+
+
+void psb_msvdx_lockup(struct drm_psb_private *dev_priv,
+                     int *msvdx_lockup, int *msvdx_idle)
+{
+       int diff;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       *msvdx_lockup = 0;
+       *msvdx_idle = 1;
+
+#if 0
+       PSB_DEBUG_GENERAL("MSVDXTimer: current_sequence:%d "
+                         "last_sequence:%d and last_submitted_sequence :%d\n",
+                         msvdx_priv->msvdx_current_sequence,
+                         msvdx_priv->msvdx_last_sequence,
+                         dev_priv->sequence[PSB_ENGINE_VIDEO]);
+#endif
+
+       diff = msvdx_priv->msvdx_current_sequence -
+              dev_priv->sequence[PSB_ENGINE_VIDEO];
+
+       if (diff > 0x0FFFFFFF) {
+               if (msvdx_priv->msvdx_current_sequence ==
+                   msvdx_priv->msvdx_last_sequence) {
+                       DRM_ERROR("MSVDXTimer:locked-up for sequence:%d\n",
+                                 msvdx_priv->msvdx_current_sequence);
+                       *msvdx_lockup = 1;
+               } else {
+                       PSB_DEBUG_GENERAL("MSVDXTimer: "
+                                         "msvdx responded fine so far\n");
+                       msvdx_priv->msvdx_last_sequence =
+                               msvdx_priv->msvdx_current_sequence;
+                       *msvdx_idle = 0;
+               }
+       }
+}
+
+int psb_check_msvdx_idle(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       /* drm_psb_msvdx_frame_info_t *current_frame = NULL; */
+
+       if (msvdx_priv->msvdx_fw_loaded == 0)
+               return 0;
+
+       if (msvdx_priv->msvdx_busy) {
+               PSB_DEBUG_PM("MSVDX: psb_check_msvdx_idle returns busy\n");
+               return -EBUSY;
+       }
+       /*
+               if (msvdx_priv->msvdx_hw_busy) {
+                       PSB_DEBUG_PM("MSVDX: %s, HW is busy\n", __func__);
+                       return -EBUSY;
+               }
+       */
+       return 0;
+}
+
+
+int psb_remove_videoctx(struct drm_psb_private *dev_priv, struct file *filp)
+{
+       struct psb_video_ctx *pos, *n;
+
+       list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+               if (pos->filp == filp) {
+                       PSB_DEBUG_GENERAL("Video:remove context profile %d,"
+                                         " entrypoint %d",
+                                         (pos->ctx_type >> 8),
+                                         (pos->ctx_type & 0xff));
+                       /*Reset fw load status here.*/
+                       if ((VAEntrypointEncSlice == (pos->ctx_type & 0xff)
+                            || VAEntrypointEncPicture ==
+                            (pos->ctx_type & 0xff)))
+                               pnw_reset_fw_status(dev_priv->dev);
+
+                       /* if current ctx points to it, set to NULL */
+                       if (dev_priv->topaz_ctx == pos)
+                               dev_priv->topaz_ctx = NULL;
+                       if (dev_priv->last_topaz_ctx == pos)
+                               dev_priv->last_topaz_ctx = NULL;
+
+                       if (dev_priv->msvdx_ctx == pos)
+                               dev_priv->msvdx_ctx = NULL;
+                       if (dev_priv->last_msvdx_ctx == pos)
+                               dev_priv->last_msvdx_ctx = NULL;
+
+                       list_del(&pos->head);
+                       kfree(pos);
+               }
+       }
+       return 0;
+}
+
+
+int lnc_video_getparam(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       struct drm_lnc_video_getparam_arg *arg = data;
+       int ret = 0;
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)file_priv->minor->dev->dev_private;
+       drm_psb_msvdx_frame_info_t *current_frame = NULL;
+       uint32_t handle, i;
+
+#if defined(CONFIG_MRST_RAR_HANDLER)
+       struct RAR_buffer rar_buf;
+       size_t rar_status;
+#endif
+       void *rar_handler;
+       uint32_t offset = 0;
+       uint32_t device_info = 0;
+       uint32_t ctx_type = 0;
+       struct psb_video_ctx *video_ctx = NULL;
+       uint32_t rar_ci_info[2];
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       switch (arg->key) {
+       case LNC_VIDEO_GETPARAM_RAR_INFO:
+               rar_ci_info[0] = dev_priv->rar_region_start;
+               rar_ci_info[1] = dev_priv->rar_region_size;
+               ret = copy_to_user((void __user *)((unsigned long)arg->value),
+                                  &rar_ci_info[0],
+                                  sizeof(rar_ci_info));
+               break;
+       case LNC_VIDEO_GETPARAM_CI_INFO:
+               rar_ci_info[0] = dev_priv->ci_region_start;
+               rar_ci_info[1] = dev_priv->ci_region_size;
+               ret = copy_to_user((void __user *)((unsigned long)arg->value),
+                                  &rar_ci_info[0],
+                                  sizeof(rar_ci_info));
+               break;
+       case LNC_VIDEO_GETPARAM_RAR_HANDLER_OFFSET:
+               ret = copy_from_user(&rar_handler,
+                                    (void __user *)((unsigned long)arg->arg),
+                                    sizeof(rar_handler));
+               if (ret)
+                       break;
+
+#if defined(CONFIG_MRST_RAR_HANDLER)
+               rar_buf.info.handle = (__u32)rar_handler;
+               rar_buf.bus_address = (dma_addr_t)dev_priv->rar_region_start;
+               rar_status = 1;
+
+               rar_status = rar_handle_to_bus(&rar_buf, 1);
+               if (rar_status != 1) {
+                       DRM_ERROR("MSVDX:rar_handle_to_bus failed\n");
+                       ret = -1;
+                       break;
+               }
+               rar_status = rar_release(&rar_buf, 1);
+               if (rar_status != 1)
+                       DRM_ERROR("MSVDX:rar_release failed\n");
+
+               offset = (uint32_t) rar_buf.bus_address - dev_priv->rar_region_start;
+               PSB_DEBUG_GENERAL("MSVDX:RAR handler %p, bus address=0x%08x,"
+                                 "RAR region=0x%08x\n",
+                                 rar_handler,
+                                 (uint32_t)rar_buf.bus_address,
+                                 dev_priv->rar_region_start);
+#endif
+               ret = copy_to_user((void __user *)((unsigned long)arg->value),
+                                  &offset,
+                                  sizeof(offset));
+               break;
+       case LNC_VIDEO_FRAME_SKIP:
+               ret = -EFAULT;
+               break;
+       case LNC_VIDEO_DEVICE_INFO:
+               device_info = 0xffff & dev_priv->video_device_fuse;
+               device_info |= (0xffff & dev->pci_device) << 16;
+
+               ret = copy_to_user((void __user *)((unsigned long)arg->value),
+                                  &device_info, sizeof(device_info));
+               break;
+       case IMG_VIDEO_NEW_CONTEXT:
+               /* add video decode/encode context */
+               ret = copy_from_user(&ctx_type, (void __user *)((unsigned long)arg->value),
+                                    sizeof(ctx_type));
+               video_ctx = kmalloc(sizeof(struct psb_video_ctx), GFP_KERNEL);
+               if (video_ctx == NULL) {
+                       ret = -ENOMEM;
+                       break;
+               }
+               INIT_LIST_HEAD(&video_ctx->head);
+               video_ctx->ctx_type = ctx_type;
+               video_ctx->filp = file_priv->filp;
+               list_add(&video_ctx->head, &dev_priv->video_ctx);
+               PSB_DEBUG_GENERAL("Video:add context profile %d, entrypoint %d",
+                                 (ctx_type >> 8), (ctx_type & 0xff));
+               break;
+
+       case IMG_VIDEO_RM_CONTEXT:
+               psb_remove_videoctx(dev_priv, file_priv->filp);
+               break;
+       case IMG_VIDEO_DECODE_STATUS:
+               if (msvdx_priv->host_be_opp_enabled) {
+                       /*get the right frame_info struct for current surface*/
+                       ret = copy_from_user(&handle,
+                                            (void __user *)((unsigned long)arg->arg), 4);
+                       if (ret) {
+                               DRM_ERROR("MSVDX in lnc_video_getparam, copy_from_user failed.\n");
+                               break;
+                       }
+
+                       for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+                               if (msvdx_priv->frame_info[i].handle == handle) {
+                                       current_frame = &msvdx_priv->frame_info[i];
+                                       break;
+                               }
+                       }
+                       if (!current_frame) {
+                               DRM_ERROR("MSVDX: didn't find frame_info which matched the surface_id. \n");
+                               return -EFAULT;
+                       }
+                       ret = copy_to_user((void __user *)((unsigned long)arg->value),
+                                          &current_frame->fw_status, sizeof(current_frame->fw_status));
+               } else
+                       ret = copy_to_user((void __user *)((unsigned long)arg->value),
+                                          &msvdx_priv->fw_status, sizeof(msvdx_priv->fw_status));
+               break;
+
+       case IMG_VIDEO_MB_ERROR:
+               /*get the right frame_info struct for current surface*/
+               ret = copy_from_user(&handle,
+                                    (void __user *)((unsigned long)arg->arg), 4);
+               if (ret)
+                       break;
+
+               for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+                       if (msvdx_priv->frame_info[i].handle == handle) {
+                               current_frame = &msvdx_priv->frame_info[i];
+                               break;
+                       }
+               }
+               if (!current_frame) {
+                       DRM_ERROR("MSVDX: didn't find frame_info which matched the surface_id. \n");
+                       return -EFAULT;
+               }
+               ret = copy_to_user((void __user *)((unsigned long)arg->value),
+                                  &(current_frame->decode_status), sizeof(drm_psb_msvdx_decode_status_t));
+               if (ret) {
+                       DRM_ERROR("lnc_video_getparam copy_to_user error.\n");
+                       return -EFAULT;
+               }
+               break;
+
+
+       default:
+               ret = -EFAULT;
+               break;
+       }
+
+       if (ret)
+               return -EFAULT;
+
+       return 0;
+}
+
+inline int psb_try_power_down_msvdx(struct drm_device *dev)
+{
+       ospm_apm_power_down_msvdx(dev);
+       return 0;
+}
+
+int psb_msvdx_save_context(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *)dev->dev_private;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       int offset = 0;
+
+       msvdx_priv->msvdx_needs_reset = 1;
+
+       for (offset = 0; offset < VEC_LOCAL_MEM_BYTE_SIZE / 4; ++offset)
+               msvdx_priv->vec_local_mem_data[offset] =
+                       PSB_RMSVDX32(VEC_LOCAL_MEM_OFFSET + offset * 4);
+
+       msvdx_priv->vec_local_mem_saved = 1;
+
+       return 0;
+}
+
+int psb_msvdx_restore_context(struct drm_device *dev)
+{
+       return 0;
+}
diff --git a/drivers/staging/mrst/imgv/psb_msvdx.h b/drivers/staging/mrst/imgv/psb_msvdx.h
new file mode 100644 (file)
index 0000000..9e63dba
--- /dev/null
@@ -0,0 +1,1384 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_MSVDX_H_
+#define _PSB_MSVDX_H_
+
+#include "psb_drv.h"
+#include "img_types.h"
+
+#if defined(CONFIG_MRST_RAR_HANDLER)
+#include "../../memrar/memrar.h"
+#endif
+
+extern int drm_msvdx_pmpolicy;
+extern int drm_msvdx_delay;
+
+typedef enum {
+       PSB_DMAC_BSWAP_NO_SWAP = 0x0,   //!< No byte swapping will be performed.
+       PSB_DMAC_BSWAP_REVERSE = 0x1,   //!< Byte order will be reversed.
+
+} DMAC_eBSwap;
+
+typedef enum {
+       PSB_DMAC_DIR_MEM_TO_PERIPH = 0x0, //!< Data from memory to peripheral.
+       PSB_DMAC_DIR_PERIPH_TO_MEM = 0x1, //!< Data from peripheral to memory.
+
+} DMAC_eDir;
+
+typedef enum {
+       PSB_DMAC_ACC_DEL_0              = 0x0,          //!< Access delay zero clock cycles
+       PSB_DMAC_ACC_DEL_256    = 0x1,      //!< Access delay 256 clock cycles
+       PSB_DMAC_ACC_DEL_512    = 0x2,      //!< Access delay 512 clock cycles
+       PSB_DMAC_ACC_DEL_768    = 0x3,      //!< Access delay 768 clock cycles
+       PSB_DMAC_ACC_DEL_1024   = 0x4,      //!< Access delay 1024 clock cycles
+       PSB_DMAC_ACC_DEL_1280   = 0x5,      //!< Access delay 1280 clock cycles
+       PSB_DMAC_ACC_DEL_1536   = 0x6,      //!< Access delay 1536 clock cycles
+       PSB_DMAC_ACC_DEL_1792   = 0x7,      //!< Access delay 1792 clock cycles
+
+} DMAC_eAccDel;
+
+typedef enum {
+       PSB_DMAC_INCR_OFF               = 0,            //!< Static peripheral address.
+       PSB_DMAC_INCR_ON                = 1                     //!< Incrementing peripheral address.
+
+} DMAC_eIncr;
+
+typedef enum {
+       PSB_DMAC_BURST_0                = 0x0,          //!< burst size of 0
+       PSB_DMAC_BURST_1        = 0x1,      //!< burst size of 1
+       PSB_DMAC_BURST_2        = 0x2,      //!< burst size of 2
+       PSB_DMAC_BURST_3        = 0x3,      //!< burst size of 3
+       PSB_DMAC_BURST_4        = 0x4,      //!< burst size of 4
+       PSB_DMAC_BURST_5        = 0x5,      //!< burst size of 5
+       PSB_DMAC_BURST_6        = 0x6,      //!< burst size of 6
+       PSB_DMAC_BURST_7        = 0x7,      //!< burst size of 7
+
+} DMAC_eBurst;
+
+int psb_wait_for_register(struct drm_psb_private *dev_priv,
+                         uint32_t offset,
+                         uint32_t value,
+                         uint32_t enable);
+
+IMG_BOOL psb_msvdx_interrupt(IMG_VOID *pvData);
+
+int psb_msvdx_init(struct drm_device *dev);
+int psb_msvdx_uninit(struct drm_device *dev);
+int psb_msvdx_reset(struct drm_psb_private *dev_priv);
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver);
+int psb_mtx_send(struct drm_psb_private *dev_priv, const void *pvMsg);
+void psb_msvdx_flush_cmd_queue(struct drm_device *dev);
+void psb_msvdx_lockup(struct drm_psb_private *dev_priv,
+                     int *msvdx_lockup, int *msvdx_idle);
+int psb_setup_fw(struct drm_device *dev);
+int psb_check_msvdx_idle(struct drm_device *dev);
+int psb_wait_msvdx_idle(struct drm_device *dev);
+int psb_cmdbuf_video(struct drm_file *priv,
+                    struct list_head *validate_list,
+                    uint32_t fence_type,
+                    struct drm_psb_cmdbuf_arg *arg,
+                    struct ttm_buffer_object *cmd_buffer,
+                    struct psb_ttm_fence_rep *fence_arg);
+int psb_msvdx_save_context(struct drm_device *dev);
+int psb_msvdx_restore_context(struct drm_device *dev);
+
+bool
+psb_host_second_pass(struct drm_device *dev,
+                    uint32_t ui32OperatingModeCmd,
+                    void        *pvParamBase,
+                    uint32_t PicWidthInMbs,
+                    uint32_t FrameHeightInMbs,
+                    uint32_t ui32DeblockSourceY,
+                    uint32_t ui32DeblockSourceUV);
+
+/*  Non-Optimal Invalidation is not default */
+#define MSVDX_DEVICE_NODE_FLAGS_MMU_NONOPT_INV 2
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK   (0x00000100)
+
+#define FW_VA_RENDER_HOST_INT          0x00004000
+#define MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION    0x00000020
+
+/* There is no work currently underway on the hardware */
+#define MSVDX_FW_STATUS_HW_IDLE        0x00000001
+#define MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE    0x00000200
+#define MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D0 \
+       (MSVDX_DEVICE_NODE_FLAGS_MMU_NONOPT_INV |                       \
+               MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION |           \
+               MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE)
+
+#define MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D1 \
+       (MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION |                  \
+               MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE)
+
+#define POULSBO_D0     0x5
+#define POULSBO_D1     0x6
+#define PSB_REVID_OFFSET 0x8
+
+#define MTX_CODE_BASE          (0x80900000)
+#define MTX_DATA_BASE          (0x82880000)
+#define PC_START_ADDRESS       (0x80900000)
+
+#define MTX_CORE_CODE_MEM      (0x10)
+#define MTX_CORE_DATA_MEM      (0x18)
+
+#define MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK         (0x00000100)
+#define MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_SHIFT                (8)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_FE_SOFT_RESET_MASK        \
+       (0x00010000)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_BE_SOFT_RESET_MASK        \
+       (0x00100000)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_VEC_MEMIF_SOFT_RESET_MASK \
+       (0x01000000)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_VEC_RENDEC_DEC_SOFT_RESET_MASK \
+       (0x10000000)
+
+#define clk_enable_all \
+(MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK        | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_MAN_CLK_ENABLE_MASK  | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK)
+
+#define clk_enable_minimal \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK
+
+#define clk_enable_auto        \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_AUTO_CLK_ENABLE_MASK        | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_AUTO_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_AUTO_CLK_ENABLE_MASK                | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_AUTO_CLK_ENABLE_MASK  | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_AUTO_CLK_ENABLE_MASK  | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK         | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK
+
+#define msvdx_sw_reset_all \
+(MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK |          \
+MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_FE_SOFT_RESET_MASK |        \
+MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_BE_SOFT_RESET_MASK        |               \
+MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_VEC_MEMIF_SOFT_RESET_MASK |       \
+MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_VEC_RENDEC_DEC_SOFT_RESET_MASK)
+
+#define MTX_INTERNAL_REG(R_SPECIFIER , U_SPECIFIER)    \
+       (((R_SPECIFIER)<<4) | (U_SPECIFIER))
+#define MTX_PC         MTX_INTERNAL_REG(0, 5)
+
+#define RENDEC_A_SIZE  (4 * 1024 * 1024)
+#define RENDEC_B_SIZE  (1024 * 1024)
+
+#define MEMIO_READ_FIELD(vpMem, field)   \
+       ((uint32_t)(((*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) \
+                       & field##_MASK) >> field##_SHIFT))
+
+#define MEMIO_WRITE_FIELD(vpMem, field, value)                         \
+       (*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) =      \
+               ((*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) \
+                       & (field##_TYPE)~field##_MASK) |                \
+       (field##_TYPE)(((uint32_t)(value) << field##_SHIFT) & field##_MASK)
+
+#define MEMIO_WRITE_FIELD_LITE(vpMem, field, value)                    \
+        (*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) =     \
+       ((*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) |     \
+               (field##_TYPE)(((uint32_t)(value) << field##_SHIFT)));
+
+#define REGIO_READ_FIELD(reg_val, reg, field)                          \
+       ((reg_val & reg##_##field##_MASK) >> reg##_##field##_SHIFT)
+
+#define REGIO_WRITE_FIELD(reg_val, reg, field, value)                  \
+       (reg_val) =                                                     \
+       ((reg_val) & ~(reg##_##field##_MASK)) |                         \
+               (((value) << (reg##_##field##_SHIFT)) & (reg##_##field##_MASK));
+
+#define REGIO_WRITE_FIELD_LITE(reg_val, reg, field, value)             \
+       (reg_val) =                                                     \
+       ((reg_val) | ((value) << (reg##_##field##_SHIFT)));
+
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK \
+       (0x00000001)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_MAN_CLK_ENABLE_MASK \
+       (0x00000002)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_MAN_CLK_ENABLE_MASK \
+       (0x00000004)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_MAN_CLK_ENABLE_MASK \
+                       (0x00000008)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_MAN_CLK_ENABLE_MASK \
+       (0x00000010)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_MAN_CLK_ENABLE_MASK \
+       (0x00000020)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK  \
+       (0x00000040)
+
+#define clk_enable_all \
+       (MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_MAN_CLK_ENABLE_MASK  | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK)
+
+#define clk_enable_minimal \
+       MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK | \
+       MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK
+
+/* MTX registers */
+#define MSVDX_MTX_ENABLE               (0x0000)
+#define MSVDX_MTX_KICKI                        (0x0088)
+#define MSVDX_MTX_KICK                 (0x0080)
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST  (0x00FC)
+#define MSVDX_MTX_REGISTER_READ_WRITE_DATA     (0x00F8)
+#define MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER     (0x0104)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL   (0x0108)
+#define MSVDX_MTX_RAM_ACCESS_STATUS    (0x010C)
+#define MSVDX_MTX_SOFT_RESET           (0x0200)
+#define MSVDX_MTX_SYSC_TIMERDIV                (0x0208)
+#define MTX_CORE_CR_MTX_SYSC_CDMAS0_OFFSET              (0x0348)
+#define MTX_CORE_CR_MTX_SYSC_CDMAA_OFFSET               (0x0344)
+#define MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET               (0x0350)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_OFFSET               (0x0340)
+
+/* MSVDX registers */
+#define MSVDX_CONTROL                  (0x0600)
+#define MSVDX_INTERRUPT_CLEAR          (0x060C)
+#define MSVDX_INTERRUPT_STATUS         (0x0608)
+#define MSVDX_HOST_INTERRUPT_ENABLE    (0x0610)
+#define MSVDX_CORE_REV                 (0x0640)
+#define MSVDX_MMU_CONTROL0             (0x0680)
+#define MSVDX_MMU_MEM_REQ              (0x06D0)
+#define MSVDX_MTX_RAM_BANK             (0x06F0)
+#define MSVDX_MTX_DEBUG                        MSVDX_MTX_RAM_BANK
+#define MSVDX_MAN_CLK_ENABLE           (0x0620)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_OFFSET              (0x0600)
+#define MSVDX_CORE_CR_MMU_BANK_INDEX_OFFSET             (0x0688)
+#define MSVDX_CORE_CR_MMU_DIR_LIST_BASE_OFFSET          (0x0694)
+#define MSVDX_CORE_CR_MMU_CONTROL0_OFFSET               MSVDX_MMU_CONTROL0
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH                (0x66c)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH                (0x678)
+
+/* RENDEC registers */
+#define MSVDX_RENDEC_CONTROL0          (0x0868)
+#define MSVDX_RENDEC_CONTROL1          (0x086C)
+#define MSVDX_RENDEC_BUFFER_SIZE       (0x0870)
+#define MSVDX_RENDEC_BASE_ADDR0                (0x0874)
+#define MSVDX_RENDEC_BASE_ADDR1                (0x0878)
+#define MSVDX_RENDEC_READ_DATA         (0x0898)
+#define MSVDX_RENDEC_CONTEXT0          (0x0950)
+#define MSVDX_RENDEC_CONTEXT1          (0x0954)
+#define MSVDX_RENDEC_CONTEXT2          (0x0958)
+#define MSVDX_RENDEC_CONTEXT3          (0x095C)
+#define MSVDX_RENDEC_CONTEXT4          (0x0960)
+#define MSVDX_RENDEC_CONTEXT5          (0x0964)
+
+/* VEC registers */
+#define MSVDX_VEC_SHIFTREG_CONTROL     (0x0818)
+
+/* DMAC registers */
+#define DMAC_DMAC_SETUP_OFFSET          (0x0500)
+#define DMAC_DMAC_COUNT_OFFSET          (0x0504)
+#define DMAC_DMAC_PERIPH_OFFSET         (0x0508)
+#define DMAC_DMAC_IRQ_STAT_OFFSET       (0x050C)
+#define DMAC_DMAC_PERIPHERAL_ADDR_OFFSET                (0x0514)
+
+/* DMAC control */
+#define PSB_DMAC_VALUE_COUNT(BSWAP,PW,DIR,PERIPH_INCR,COUNT)                                \
+                                                                                                                                                \
+    (((BSWAP)           & DMAC_DMAC_COUNT_BSWAP_LSBMASK)        << DMAC_DMAC_COUNT_BSWAP_SHIFT) | \
+        (((PW)                  & DMAC_DMAC_COUNT_PW_LSBMASK)           << DMAC_DMAC_COUNT_PW_SHIFT)    | \
+        (((DIR)                 & DMAC_DMAC_COUNT_DIR_LSBMASK)          << DMAC_DMAC_COUNT_DIR_SHIFT)   | \
+        (((PERIPH_INCR) & DMAC_DMAC_COUNT_PI_LSBMASK)           << DMAC_DMAC_COUNT_PI_SHIFT)    | \
+        (((COUNT)               & DMAC_DMAC_COUNT_CNT_LSBMASK)          << DMAC_DMAC_COUNT_CNT_SHIFT)
+
+#define PSB_DMAC_VALUE_PERIPH_PARAM(ACC_DEL,INCR,BURST)                                             \
+                                                                                                                                                \
+        (((ACC_DEL)     & DMAC_DMAC_PERIPH_ACC_DEL_LSBMASK)     << DMAC_DMAC_PERIPH_ACC_DEL_SHIFT)      | \
+        (((INCR)        & DMAC_DMAC_PERIPH_INCR_LSBMASK)        << DMAC_DMAC_PERIPH_INCR_SHIFT)         | \
+        (((BURST)       & DMAC_DMAC_PERIPH_BURST_LSBMASK)       << DMAC_DMAC_PERIPH_BURST_SHIFT)
+
+
+/* CMD */
+#define MSVDX_CMDS_END_SLICE_PICTURE   (0x1404)
+
+/*
+ * This defines the MSVDX communication buffer
+ */
+#define MSVDX_COMMS_SIGNATURE_VALUE    (0xA5A5A5A5)    /*!< Signature value */
+/*!< Host buffer size (in 32-bit words) */
+#define NUM_WORDS_HOST_BUF             (100)
+/*!< MTX buffer size (in 32-bit words) */
+#define NUM_WORDS_MTX_BUF              (100)
+
+/* There is no work currently underway on the hardware */
+#define MSVDX_FW_STATUS_HW_IDLE        0x00000001
+
+#define MSVDX_EXT_FW_ERROR_STATE (0x2884)
+#define MSVDX_COMMS_AREA_ADDR (0x02fe0)
+
+#define MSVDX_COMMS_CORE_WTD                   (MSVDX_COMMS_AREA_ADDR - 0x08)
+#define MSVDX_COMMS_ERROR_TRIG                 (MSVDX_COMMS_AREA_ADDR - 0x08)
+#define MSVDX_COMMS_FIRMWARE_ID                        (MSVDX_COMMS_AREA_ADDR - 0x0C)
+#define MSVDX_COMMS_OFFSET_FLAGS               (MSVDX_COMMS_AREA_ADDR + 0x18)
+#define        MSVDX_COMMS_MSG_COUNTER                 (MSVDX_COMMS_AREA_ADDR - 0x04)
+#define MSVDX_COMMS_FW_STATUS                  (MSVDX_COMMS_AREA_ADDR - 0x10)
+#define        MSVDX_COMMS_SIGNATURE                   (MSVDX_COMMS_AREA_ADDR + 0x00)
+#define        MSVDX_COMMS_TO_HOST_BUF_SIZE            (MSVDX_COMMS_AREA_ADDR + 0x04)
+#define MSVDX_COMMS_TO_HOST_RD_INDEX           (MSVDX_COMMS_AREA_ADDR + 0x08)
+#define MSVDX_COMMS_TO_HOST_WRT_INDEX          (MSVDX_COMMS_AREA_ADDR + 0x0C)
+#define MSVDX_COMMS_TO_MTX_BUF_SIZE            (MSVDX_COMMS_AREA_ADDR + 0x10)
+#define MSVDX_COMMS_TO_MTX_RD_INDEX            (MSVDX_COMMS_AREA_ADDR + 0x14)
+#define MSVDX_COMMS_TO_MTX_CB_RD_INDEX         (MSVDX_COMMS_AREA_ADDR + 0x18)
+#define MSVDX_COMMS_TO_MTX_WRT_INDEX           (MSVDX_COMMS_AREA_ADDR + 0x1C)
+#define MSVDX_COMMS_TO_HOST_BUF                        (MSVDX_COMMS_AREA_ADDR + 0x20)
+#define MSVDX_COMMS_TO_MTX_BUF \
+       (MSVDX_COMMS_TO_HOST_BUF + (NUM_WORDS_HOST_BUF << 2))
+
+#define DSIABLE_FW_WDT                         0x0008
+#define ABORT_ON_ERRORS_IMMEDIATE       0x0010
+#define ABORT_FAULTED_SLICE_IMMEDIATE   0x0020
+#define RETURN_VDEB_DATA_IN_COMPLETION  0x0800
+#define DSIABLE_Auto_CLOCK_GATING          0x1000
+#define DSIABLE_IDLE_GPIO_SIG                  0x2000
+/*
+#define MSVDX_COMMS_AREA_END   \
+  (MSVDX_COMMS_TO_MTX_BUF + (NUM_WORDS_HOST_BUF << 2))
+*/
+#define MSVDX_COMMS_AREA_END 0x03000
+
+#if (MSVDX_COMMS_AREA_END != 0x03000)
+#error
+#endif
+
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK  (0x80000000)
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_SHIFT (31)
+
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_MASK     (0x00010000)
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_SHIFT    (16)
+
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMID_MASK            (0x0FF00000)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMID_SHIFT           (20)
+
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCM_ADDR_MASK (0x000FFFFC)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCM_ADDR_SHIFT        (2)
+
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMAI_MASK    (0x00000002)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMAI_SHIFT   (1)
+
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMR_MASK     (0x00000001)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMR_SHIFT    (0)
+
+#define MSVDX_MTX_SOFT_RESET_MTX_RESET_MASK            (0x00000001)
+#define MSVDX_MTX_SOFT_RESET_MTX_RESET_SHIFT           (0)
+
+#define MSVDX_MTX_ENABLE_MTX_ENABLE_MASK               (0x00000001)
+#define MSVDX_MTX_ENABLE_MTX_ENABLE_SHIFT              (0)
+
+#define MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK         (0x00000100)
+#define MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_SHIFT                (8)
+
+#define MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK   (0x00000F00)
+#define MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_SHIFT  (8)
+
+#define MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK         (0x00004000)
+#define MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_SHIFT                (14)
+
+#define MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK                   (0x00000002)
+#define MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_SHIFT                  (1)
+
+#define MSVDX_MTX_RAM_BANK_CR_MTX_RAM_BANK_SIZE_MASK           (0x000F0000)
+#define MSVDX_MTX_RAM_BANK_CR_MTX_RAM_BANK_SIZE_SHIFT          (16)
+
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_MASK                (0x00000004)
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_LSBMASK             (0x00000001)
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_SHIFT               (2)
+
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_MASK         (0x00000003)
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_LSBMASK              (0x00000003)
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_SHIFT                (0)
+
+#define MSVDX_RENDEC_BUFFER_SIZE_RENDEC_BUFFER_SIZE0_MASK      (0x0000FFFF)
+#define MSVDX_RENDEC_BUFFER_SIZE_RENDEC_BUFFER_SIZE0_SHIFT     (0)
+
+#define MSVDX_RENDEC_BUFFER_SIZE_RENDEC_BUFFER_SIZE1_MASK      (0xFFFF0000)
+#define MSVDX_RENDEC_BUFFER_SIZE_RENDEC_BUFFER_SIZE1_SHIFT     (16)
+
+#define MSVDX_RENDEC_CONTROL1_RENDEC_DECODE_START_SIZE_MASK    (0x000000FF)
+#define MSVDX_RENDEC_CONTROL1_RENDEC_DECODE_START_SIZE_SHIFT   (0)
+
+#define MSVDX_RENDEC_CONTROL1_RENDEC_BURST_SIZE_W_MASK         (0x000C0000)
+#define MSVDX_RENDEC_CONTROL1_RENDEC_BURST_SIZE_W_SHIFT                (18)
+
+#define MSVDX_RENDEC_CONTROL1_RENDEC_BURST_SIZE_R_MASK         (0x00030000)
+#define MSVDX_RENDEC_CONTROL1_RENDEC_BURST_SIZE_R_SHIFT                (16)
+
+#define MSVDX_RENDEC_CONTROL1_RENDEC_EXTERNAL_MEMORY_MASK      (0x01000000)
+#define MSVDX_RENDEC_CONTROL1_RENDEC_EXTERNAL_MEMORY_SHIFT     (24)
+
+#define MSVDX_RENDEC_CONTROL0_RENDEC_INITIALISE_MASK           (0x00000001)
+#define MSVDX_RENDEC_CONTROL0_RENDEC_INITIALISE_SHIFT          (0)
+
+#define VEC_SHIFTREG_CONTROL_SR_MASTER_SELECT_MASK         (0x00000300)
+#define VEC_SHIFTREG_CONTROL_SR_MASTER_SELECT_SHIFT                (8)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_BURSTSIZE_MASK               (0x07000000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_BURSTSIZE_SHIFT              (24)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_RNW_MASK             (0x00020000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_RNW_SHIFT            (17)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_ENABLE_MASK          (0x00010000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_ENABLE_SHIFT         (16)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_LENGTH_MASK          (0x0000FFFF)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_LENGTH_SHIFT         (0)
+
+#define MSVDX_CORE_CR_MSVDX_CONTROL_DMAC_CH0_SELECT_MASK                (0x00001000)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_DMAC_CH0_SELECT_SHIFT               (12)
+
+#define MSVDX_CORE_CR_MMU_CONTROL0_CR_MMU_INVALDC_MASK          (0x00000008)
+#define MSVDX_CORE_CR_MMU_CONTROL0_CR_MMU_INVALDC_SHIFT         (3)
+
+#define DMAC_DMAC_COUNT_BSWAP_LSBMASK           (0x00000001)
+#define DMAC_DMAC_COUNT_BSWAP_SHIFT             (30)
+
+#define DMAC_DMAC_COUNT_PW_LSBMASK              (0x00000003)
+#define DMAC_DMAC_COUNT_PW_SHIFT                (27)
+
+#define DMAC_DMAC_COUNT_DIR_LSBMASK             (0x00000001)
+#define DMAC_DMAC_COUNT_DIR_SHIFT               (26)
+
+#define DMAC_DMAC_COUNT_PI_LSBMASK              (0x00000003)
+#define DMAC_DMAC_COUNT_PI_SHIFT                (24)
+
+#define DMAC_DMAC_COUNT_CNT_LSBMASK             (0x0000FFFF)
+#define DMAC_DMAC_COUNT_CNT_SHIFT               (0)
+
+#define DMAC_DMAC_PERIPH_ACC_DEL_LSBMASK                (0x00000007)
+#define DMAC_DMAC_PERIPH_ACC_DEL_SHIFT          (29)
+
+#define DMAC_DMAC_PERIPH_INCR_LSBMASK           (0x00000001)
+#define DMAC_DMAC_PERIPH_INCR_SHIFT             (27)
+
+#define DMAC_DMAC_PERIPH_BURST_LSBMASK          (0x00000007)
+#define DMAC_DMAC_PERIPH_BURST_SHIFT            (24)
+
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_MASK             (0x007FFFFF)
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_LSBMASK          (0x007FFFFF)
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_SHIFT            (0)
+
+#define DMAC_DMAC_COUNT_EN_MASK         (0x00010000)
+#define DMAC_DMAC_COUNT_EN_SHIFT                (16)
+
+#define DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK            (0x00020000)
+
+/*watch dog for FE and BE*/
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_OFFSET              (0x0064)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CNT_CTRL
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_MASK                (0x00060000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_LSBMASK             (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_SHIFT               (17)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ENABLE
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_MASK          (0x00010000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_LSBMASK               (0x00000001)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_SHIFT         (16)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION1
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_MASK         (0x00003000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_LSBMASK              (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_SHIFT                (12)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION0
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_MASK         (0x00000100)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_LSBMASK              (0x00000001)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_SHIFT                (8)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLEAR_SELECT
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_MASK            (0x00000030)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_LSBMASK         (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_SHIFT           (4)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLKDIV_SELECT
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_MASK           (0x00000007)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_LSBMASK                (0x00000007)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_SHIFT          (0)
+
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_OFFSET          (0x0068)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDTIMER, FE_WDT_COUNTER
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_MASK             (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_LSBMASK          (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_SHIFT            (0)
+
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_OFFSET         (0x006C)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_COMPAREMATCH, FE_WDT_CM1
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_MASK                (0xFFFF0000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_LSBMASK             (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_SHIFT               (16)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_COMPAREMATCH, FE_WDT_CM0
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_MASK                (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_LSBMASK             (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_SHIFT               (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_OFFSET              (0x0070)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CNT_CTRL
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_MASK                (0x001E0000)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_LSBMASK             (0x0000000F)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_SHIFT               (17)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ENABLE
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_MASK          (0x00010000)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_LSBMASK               (0x00000001)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_SHIFT         (16)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ACTION0
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_MASK         (0x00000100)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_LSBMASK              (0x00000001)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_SHIFT                (8)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLEAR_SELECT
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_MASK            (0x000000F0)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_LSBMASK         (0x0000000F)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_SHIFT           (4)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLKDIV_SELECT
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_MASK           (0x00000007)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_LSBMASK                (0x00000007)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_SHIFT          (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_OFFSET          (0x0074)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDTIMER, BE_WDT_COUNTER
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_MASK             (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_LSBMASK          (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_SHIFT            (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_OFFSET         (0x0078)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_COMPAREMATCH, BE_WDT_CM0
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_MASK                (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_LSBMASK             (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_SHIFT               (0)
+/*watch dog end*/
+
+/* Start of parser specific Host->MTX messages. */
+#define        FWRK_MSGID_START_PSR_HOSTMTX_MSG        (0x80)
+
+/* Start of parser specific MTX->Host messages. */
+#define        FWRK_MSGID_START_PSR_MTXHOST_MSG        (0xC0)
+
+/* Host defined msg, just for host use, MTX not recgnize */
+#define        FWRK_MSGID_HOST_EMULATED                (0x40)
+
+#define FWRK_MSGID_PADDING                     (0)
+
+#define FWRK_GENMSG_SIZE_TYPE          uint8_t
+#define FWRK_GENMSG_SIZE_MASK          (0xFF)
+#define FWRK_GENMSG_SIZE_SHIFT         (0)
+#define FWRK_GENMSG_SIZE_OFFSET                (0x0000)
+#define FWRK_GENMSG_ID_TYPE            uint8_t
+#define FWRK_GENMSG_ID_MASK            (0xFF)
+#define FWRK_GENMSG_ID_SHIFT           (0)
+#define FWRK_GENMSG_ID_OFFSET          (0x0001)
+#define FWRK_PADMSG_SIZE               (2)
+
+/* Deblock CMD_ID */
+#define MSVDX_DEBLOCK_REG_SET   0x10000000
+#define MSVDX_DEBLOCK_REG_GET   0x20000000
+#define MSVDX_DEBLOCK_REG_POLLn 0x30000000
+#define MSVDX_DEBLOCK_REG_POLLx 0x40000000
+
+/* vec local MEM save/restore */
+#define VEC_LOCAL_MEM_BYTE_SIZE (4 * 1024)
+#define VEC_LOCAL_MEM_OFFSET 0x2000
+
+/* This type defines the framework specified message ids */
+enum {
+       /* ! Sent by the DXVA driver on the host to the mtx firmware.
+        */
+       VA_MSGID_INIT = FWRK_MSGID_START_PSR_HOSTMTX_MSG,
+       VA_MSGID_RENDER,
+       VA_MSGID_DEBLOCK,
+       VA_MSGID_OOLD,
+
+       /* Test Messages */
+       VA_MSGID_TEST1,
+       VA_MSGID_HOST_BE_OPP,
+
+       /*! Sent by the mtx firmware to itself.
+        */
+       VA_MSGID_RENDER_MC_INTERRUPT,
+
+       VA_MSGID_DEBLOCK_MFLD = FWRK_MSGID_HOST_EMULATED,
+       VA_MSGID_OOLD_MFLD,
+       /*! Sent by the DXVA firmware on the MTX to the host.
+        */
+       VA_MSGID_CMD_COMPLETED = FWRK_MSGID_START_PSR_MTXHOST_MSG,
+       VA_MSGID_CMD_COMPLETED_BATCH,
+       VA_MSGID_DEBLOCK_REQUIRED,
+       VA_MSGID_TEST_RESPONCE,
+       VA_MSGID_ACK,
+
+       VA_MSGID_CMD_FAILED,
+       VA_MSGID_CMD_CONTIGUITY_WARNING,
+       VA_MSGID_CMD_HW_PANIC,
+};
+
+/* Deblock parameters */
+struct DEBLOCKPARAMS {
+       uint32_t handle;        /* struct ttm_buffer_object * of REGIO */
+       uint32_t buffer_size;
+       uint32_t ctxid;
+
+       uint32_t *pPicparams;
+       struct ttm_bo_kmap_obj *regio_kmap;     /* virtual of regio */
+       uint32_t pad[3];
+};
+
+/* HOST_BE_OPP parameters */
+struct HOST_BE_OPP_PARAMS {
+       uint32_t handle;        /* struct ttm_buffer_object * of REGIO */
+       uint32_t buffer_stride;
+       uint32_t buffer_size;
+       uint32_t picture_width_mb;
+       uint32_t size_mb;
+};
+struct psb_msvdx_deblock_queue {
+
+       struct list_head head;
+       struct DEBLOCKPARAMS dbParams;
+};
+
+typedef struct {
+       union {
+               struct {
+                       uint32_t msg_size       : 8;
+                       uint32_t msg_type       : 8;
+                       uint32_t msg_fence      : 16;
+               } bits;
+               uint32_t value;
+       } header;
+       uint32_t flags;
+       uint32_t operating_mode;
+       union {
+               struct {
+                       uint32_t context        : 8;
+                       uint32_t mmu_ptd        : 24;
+               } bits;
+               uint32_t value;
+       } mmu_context;
+       union {
+               struct {
+                       uint32_t frame_height_mb        : 16;
+                       uint32_t pic_width_mb   : 16;
+               } bits;
+               uint32_t value;
+       } pic_size;
+       uint32_t address_a0;
+       uint32_t address_a1;
+       uint32_t mb_param_address;
+       uint32_t address_b0;
+       uint32_t address_b1;
+       uint32_t rotation_flags;
+} FW_VA_DEBLOCK_MSG;
+
+typedef struct drm_psb_msvdx_frame_info {
+       uint32_t handle;
+       uint32_t surface_id;
+       uint32_t fence;
+       uint32_t buffer_stride;
+       uint32_t buffer_size;
+       uint32_t picture_width_mb;
+       uint32_t fw_status;
+       uint32_t size_mb;
+       drm_psb_msvdx_decode_status_t decode_status;
+} drm_psb_msvdx_frame_info_t;
+
+#define MAX_DECODE_BUFFERS 24
+/* MSVDX private structure */
+struct msvdx_private {
+       int msvdx_needs_reset;
+
+       unsigned int pmstate;
+
+       struct sysfs_dirent *sysfs_pmstate;
+
+       uint32_t msvdx_current_sequence;
+       uint32_t msvdx_last_sequence;
+
+       /*
+        *MSVDX Rendec Memory
+        */
+       struct ttm_buffer_object *ccb0;
+       uint32_t base_addr0;
+       struct ttm_buffer_object *ccb1;
+       uint32_t base_addr1;
+
+       struct ttm_buffer_object *fw;
+       uint32_t is_load;
+       uint32_t mtx_mem_size;
+
+       /*
+        *msvdx command queue
+        */
+       spinlock_t msvdx_lock;
+       struct mutex msvdx_mutex;
+       struct list_head msvdx_queue;
+       int msvdx_busy;
+       int msvdx_fw_loaded;
+       void *msvdx_fw;
+       int msvdx_fw_size;
+
+       struct list_head deblock_queue; /* deblock parameter list */
+
+       uint32_t msvdx_hw_busy;
+
+       uint32_t *vec_local_mem_data;
+       uint32_t vec_local_mem_size;
+       uint32_t vec_local_mem_saved;
+       uint32_t psb_dash_access_ctrl;
+       uint32_t fw_status;
+
+       drm_psb_msvdx_frame_info_t frame_info[MAX_DECODE_BUFFERS];
+       drm_psb_msvdx_decode_status_t decode_status;
+       uint32_t deblock_enabled;
+       uint32_t host_be_opp_enabled;
+
+       uint32_t ec_fence;
+       uint32_t ref_pic_fence;
+       /*work for error concealment*/
+       struct work_struct ec_work;
+       struct ttm_object_file *tfile;
+};
+
+#define REGISTER(__group__, __reg__ )  (__group__##_##__reg__##_OFFSET)
+/* MSVDX Firmware interface */
+#define FW_VA_INIT_SIZE                        (8)
+#define FW_VA_DEBUG_TEST2_SIZE         (4)
+
+/*MESSAGE SENT FROM HOST TO FW*/
+/*FW_VA_RENDER MESSAGE*/
+/* FW_VA_RENDER     BUFFER_SIZE */
+#define FW_VA_RENDER_BUFFER_SIZE_TYPE           uint16_t
+#define FW_VA_RENDER_BUFFER_SIZE_MASK           (0x0FFF)
+#define FW_VA_RENDER_BUFFER_SIZE_OFFSET         (0x0002)
+#define FW_VA_RENDER_BUFFER_SIZE_SHIFT          (0)
+
+/* FW_VA_RENDER     MMUPTD */
+#define FW_VA_RENDER_MMUPTD_TYPE               uint32_t
+#define FW_VA_RENDER_MMUPTD_MASK               (0xFFFFFFFF)
+#define FW_VA_RENDER_MMUPTD_OFFSET             (0x0004)
+#define FW_VA_RENDER_MMUPTD_SHIFT              (0)
+
+/* FW_VA_RENDER     LLDMA_ADDRESS */
+#define FW_VA_RENDER_LLDMA_ADDRESS_START_BIT           0
+#define FW_VA_RENDER_LLDMA_ADDRESS_END_BIT             31
+#define FW_VA_RENDER_LLDMA_ADDRESS_ALIGNMENT           (4)
+#define FW_VA_RENDER_LLDMA_ADDRESS_TYPE                uint32_t
+#define FW_VA_RENDER_LLDMA_ADDRESS_MASK                (0xFFFFFFFF)
+#define FW_VA_RENDER_LLDMA_ADDRESS_LSBMASK             (0xFFFFFFFF)
+#define FW_VA_RENDER_LLDMA_ADDRESS_OFFSET              (0x0008)
+#define FW_VA_RENDER_LLDMA_ADDRESS_SHIFT               (0)
+#define FW_VA_RENDER_LLDMA_ADDRESS_SIGNED_FIELD        (0)
+
+/* FW_VA_RENDER     CONTEXT */
+#define FW_VA_RENDER_CONTEXT_START_BIT         0
+#define FW_VA_RENDER_CONTEXT_END_BIT           31
+#define FW_VA_RENDER_CONTEXT_ALIGNMENT         (4)
+#define FW_VA_RENDER_CONTEXT_TYPE              uint32_t
+#define FW_VA_RENDER_CONTEXT_MASK              (0xFFFFFFFF)
+#define FW_VA_RENDER_CONTEXT_LSBMASK           (0xFFFFFFFF)
+#define FW_VA_RENDER_CONTEXT_OFFSET            (0x000C)
+#define FW_VA_RENDER_CONTEXT_SHIFT             (0)
+#define FW_VA_RENDER_CONTEXT_SIGNED_FIELD      (0)
+
+
+/* FW_VA_RENDER     FENCE_VALUE_NO_EC */
+#define FW_VA_RENDER_FENCE_VALUE_TYPE          uint32_t
+#define FW_VA_RENDER_FENCE_VALUE_MASK          (0xFFFFFFFF)
+#define FW_VA_RENDER_FENCE_VALUE_OFFSET                (0x0010)
+#define FW_VA_RENDER_FENCE_VALUE_SHIFT         (0)
+
+/* FW_VA_RENDER     OPERATING_MODE */
+#define FW_VA_RENDER_OPERATING_MODE_ALIGNMENT          (4)
+#define FW_VA_RENDER_OPERATING_MODE_TYPE               uint32_t
+#define FW_VA_RENDER_OPERATING_MODE_MASK               (0xFFFFFFFF)
+#define FW_VA_RENDER_OPERATING_MODE_LSBMASK            (0xFFFFFFFF)
+#define FW_VA_RENDER_OPERATING_MODE_OFFSET             (0x0014)
+#define FW_VA_RENDER_OPERATING_MODE_SHIFT              (0)
+#define FW_VA_RENDER_OPERATING_MODE_SIGNED_FIELD       (0)
+
+/* FW_VA_RENDER     FIRST_MB_IN_SLICE */
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_START_BIT               0
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_END_BIT         15
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_ALIGNMENT               (2)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_TYPE            uint16_t
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_MASK            (0xFFFF)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_LSBMASK         (0xFFFF)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_OFFSET          (0x0018)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_SHIFT           (0)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_SIGNED_FIELD    (0)
+
+/* FW_VA_RENDER     LAST_MB_IN_FRAME */
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_START_BIT                16
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_END_BIT          31
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_ALIGNMENT                (2)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_TYPE             uint16_t
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_MASK             (0xFFFF)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_LSBMASK          (0xFFFF)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_OFFSET           (0x001A)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_SHIFT            (0)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_SIGNED_FIELD     (0)
+
+/* FW_VA_RENDER     FLAGS */
+#define FW_VA_RENDER_FLAGS_START_BIT           0
+#define FW_VA_RENDER_FLAGS_END_BIT             31
+#define FW_VA_RENDER_FLAGS_ALIGNMENT           (4)
+#define FW_VA_RENDER_FLAGS_TYPE                uint32_t
+#define FW_VA_RENDER_FLAGS_MASK                (0xFFFFFFFF)
+#define FW_VA_RENDER_FLAGS_LSBMASK             (0xFFFFFFFF)
+#define FW_VA_RENDER_FLAGS_OFFSET              (0x001C)
+#define FW_VA_RENDER_FLAGS_SHIFT               (0)
+#define FW_VA_RENDER_FLAGS_SIGNED_FIELD        (0)
+/* FW_VA_DEBUG_TEST2     MSG_SIZE */
+#define FW_VA_DEBUG_TEST2_MSG_SIZE_TYPE                uint8_t
+#define FW_VA_DEBUG_TEST2_MSG_SIZE_MASK                (0xFF)
+#define FW_VA_DEBUG_TEST2_MSG_SIZE_OFFSET      (0x0000)
+#define FW_VA_DEBUG_TEST2_MSG_SIZE_SHIFT       (0)
+
+/* FW_VA_DEBUG_TEST2     ID */
+#define FW_VA_DEBUG_TEST2_ID_TYPE              uint8_t
+#define FW_VA_DEBUG_TEST2_ID_MASK              (0xFF)
+#define FW_VA_DEBUG_TEST2_ID_OFFSET            (0x0001)
+#define FW_VA_DEBUG_TEST2_ID_SHIFT             (0)
+
+/* FW_VA_CMD_FAILED     FENCE_VALUE */
+#define FW_VA_CMD_FAILED_FENCE_VALUE_TYPE      uint32_t
+#define FW_VA_CMD_FAILED_FENCE_VALUE_MASK      (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_FENCE_VALUE_OFFSET    (0x0004)
+#define FW_VA_CMD_FAILED_FENCE_VALUE_SHIFT     (0)
+
+/* FW_VA_CMD_FAILED     IRQSTATUS */
+#define FW_VA_CMD_FAILED_IRQSTATUS_TYPE                uint32_t
+#define FW_VA_CMD_FAILED_IRQSTATUS_MASK                (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_IRQSTATUS_OFFSET      (0x0008)
+#define FW_VA_CMD_FAILED_IRQSTATUS_SHIFT       (0)
+/*FW_DXVA_DEBLOCK MESSAGE*/
+/* FW_DXVA_DEBLOCK     MSG_SIZE */
+#define FW_DXVA_DEBLOCK_MSG_SIZE_ALIGNMENT              (1)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_TYPE           uint8_t
+#define FW_DXVA_DEBLOCK_MSG_SIZE_MASK           (0xFF)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_LSBMASK                (0xFF)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_OFFSET         (0x0000)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_SHIFT          (0)
+
+/* FW_DXVA_DEBLOCK     ID */
+#define FW_DXVA_DEBLOCK_ID_ALIGNMENT            (1)
+#define FW_DXVA_DEBLOCK_ID_TYPE         uint8_t
+#define FW_DXVA_DEBLOCK_ID_MASK         (0xFF)
+#define FW_DXVA_DEBLOCK_ID_LSBMASK              (0xFF)
+#define FW_DXVA_DEBLOCK_ID_OFFSET               (0x0001)
+#define FW_DXVA_DEBLOCK_ID_SHIFT                (0)
+
+// FW_DXVA_DEBLOCK     FLAGS
+#define FW_DXVA_DEBLOCK_FLAGS_START_BIT                16
+#define FW_DXVA_DEBLOCK_FLAGS_END_BIT          31
+#define FW_DXVA_DEBLOCK_FLAGS_ALIGNMENT                (2)
+#define FW_DXVA_DEBLOCK_FLAGS_TYPE             uint16_t
+#define FW_DXVA_DEBLOCK_FLAGS_MASK             (0xFFFF)
+#define FW_DXVA_DEBLOCK_FLAGS_LSBMASK          (0xFFFF)
+#define FW_DXVA_DEBLOCK_FLAGS_OFFSET           (0x0002)
+#define FW_DXVA_DEBLOCK_FLAGS_SHIFT            (0)
+#define FW_DXVA_DEBLOCK_FLAGS_SIGNED_FIELD     (0)
+
+/* FW_DXVA_DEBLOCK     CONTEXT */
+#define FW_DXVA_DEBLOCK_CONTEXT_START_BIT              0
+#define FW_DXVA_DEBLOCK_CONTEXT_END_BIT                11
+#define FW_DXVA_DEBLOCK_CONTEXT_ALIGNMENT              (4)
+#define FW_DXVA_DEBLOCK_CONTEXT_TYPE           uint16_t
+#define FW_DXVA_DEBLOCK_CONTEXT_MASK           (0xFFF)
+#define FW_DXVA_DEBLOCK_CONTEXT_LSBMASK                (0xFFF)
+#define FW_DXVA_DEBLOCK_CONTEXT_OFFSET         (0x0004)
+#define FW_DXVA_DEBLOCK_CONTEXT_SHIFT          (0)
+#define FW_DXVA_DEBLOCK_CONTEXT_SIGNED_FIELD   (0)
+
+
+/* FW_DXVA_DEBLOCK     CONTEXT_NO_EC */
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_START_BIT                0
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_END_BIT          31
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_ALIGNMENT                (4)
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_TYPE             uint32_t
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_MASK             (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_LSBMASK          (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_OFFSET           (0x0004)
+#define FW_DXVA_DEBLOCK_CONTEXT_SHIFT          (0)
+#define FW_DXVA_DEBLOCK_CONTEXT_SIGNED_FIELD   (0)
+
+/* FW_DXVA_DEBLOCK     FENCE_VALUE_NO_EC */
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_START_BIT            0
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_END_BIT              31
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_ALIGNMENT            (4)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_TYPE         uint32_t
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_MASK         (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_LSBMASK              (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_OFFSET               (0x0008)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_SHIFT                (0)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_SIGNED_FIELD (0)
+
+
+/* FW_DXVA_DEBLOCK     MMUPTD */
+#define FW_DXVA_DEBLOCK_MMUPTD_START_BIT               0
+#define FW_DXVA_DEBLOCK_MMUPTD_END_BIT         31
+#define FW_DXVA_DEBLOCK_MMUPTD_ALIGNMENT               (4)
+#define FW_DXVA_DEBLOCK_MMUPTD_TYPE            uint32_t
+#define FW_DXVA_DEBLOCK_MMUPTD_MASK            (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_MMUPTD_LSBMASK         (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_MMUPTD_OFFSET          (0x000C)
+#define FW_DXVA_DEBLOCK_MMUPTD_SHIFT           (0)
+#define FW_DXVA_DEBLOCK_MMUPTD_SIGNED_FIELD    (0)
+
+
+/* FW_VA_HOST_BE_OPP     MMUPTD */
+#define FW_VA_HOST_BE_OPP_MMUPTD_ALIGNMENT                (4)
+#define FW_VA_HOST_BE_OPP_MMUPTD_TYPE             uint32_t
+#define FW_VA_HOST_BE_OPP_MMUPTD_MASK             (0xFFFFFFFF)
+#define FW_VA_HOST_BE_OPP_MMUPTD_LSBMASK          (0xFFFFFFFF)
+#define FW_VA_HOST_BE_OPP_MMUPTD_OFFSET           (0x000C)
+#define FW_VA_HOST_BE_OPP_MMUPTD_SHIFT            (0)
+
+
+/*MESSAGE SENT FROM FW TO HOST*/
+
+/* FW_VA_CMD_COMPLETED MESSAGE*/
+/* FW_VA_CMD_COMPLETED     LASTMB */
+#define FW_VA_CMD_COMPLETED_LASTMB_ALIGNMENT           (2)
+#define FW_VA_CMD_COMPLETED_LASTMB_TYPE                uint16_t
+#define FW_VA_CMD_COMPLETED_LASTMB_MASK                (0xFFFF)
+#define FW_VA_CMD_COMPLETED_LASTMB_LSBMASK             (0xFFFF)
+#define FW_VA_CMD_COMPLETED_LASTMB_OFFSET              (0x0002)
+#define FW_VA_CMD_COMPLETED_LASTMB_SHIFT               (0)
+#define FW_VA_CMD_COMPLETED_LASTMB_SIGNED_FIELD        (0)
+
+/* FW_VA_CMD_COMPLETED     NO_TICKSNO_EC */
+#define FW_VA_CMD_COMPLETED_NO_TICKS_NO_EC_TYPE        uint16_t
+#define FW_VA_CMD_COMPLETED_NO_TICKS_NO_EC_MASK        (0xFFFF)
+#define FW_VA_CMD_COMPLETED_NO_TICKS_NO_EC_OFFSET      (0x0002)
+#define FW_VA_CMD_COMPLETED_NO_TICKS_NO_EC_SHIFT       (0)
+/* FW_VA_CMD_COMPLETED     FENCE_VALUE */
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_TYPE   uint32_t
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_MASK   (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_OFFSET (0x0004)
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_SHIFT  (0)
+
+/* FW_VA_CMD_COMPLETED     FENCE_VALUE_NO_EC */
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_NO_EC_TYPE     uint32_t
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_NO_EC_MASK     (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_NO_EC_OFFSET   (0x0004)
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_NO_EC_SHIFT    (0)
+
+/* FW_VA_CMD_COMPLETED     FLAGS */
+#define FW_VA_CMD_COMPLETED_FLAGS_ALIGNMENT            (4)
+#define FW_VA_CMD_COMPLETED_FLAGS_TYPE         uint32_t
+#define FW_VA_CMD_COMPLETED_FLAGS_MASK         (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_FLAGS_LSBMASK              (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_FLAGS_OFFSET               (0x0008)
+#define FW_VA_CMD_COMPLETED_FLAGS_SHIFT                (0)
+
+/* FW_VA_CMD_COMPLETED     NO_TICKS */
+#define FW_VA_CMD_COMPLETED_NO_TICKS_TYPE      uint16_t
+#define FW_VA_CMD_COMPLETED_NO_TICKS_MASK      (0xFFFF)
+#define FW_VA_CMD_COMPLETED_NO_TICKS_OFFSET    (0x0002)
+#define FW_VA_CMD_COMPLETED_NO_TICKS_SHIFT     (0)
+
+
+/* FW_VA_DEBLOCK_REQUIRED     CONTEXT */
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_TYPE    uint16_t
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_MASK    (0xFFF)
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_OFFSET  (0x0004)
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_SHIFT   (0)
+
+/* FW_VA_INIT     GLOBAL_PTD */
+#define FW_VA_INIT_GLOBAL_PTD_TYPE             uint32_t
+#define FW_VA_INIT_GLOBAL_PTD_MASK             (0xFFFFFFFF)
+#define FW_VA_INIT_GLOBAL_PTD_OFFSET           (0x0004)
+#define FW_VA_INIT_GLOBAL_PTD_SHIFT            (0)
+
+/* FW_VA_RENDER     FENCE_VALUE */
+#define FW_VA_RENDER_FENCE_VALUE_TYPE          uint32_t
+#define FW_VA_RENDER_FENCE_VALUE_MASK          (0xFFFFFFFF)
+#define FW_VA_RENDER_FENCE_VALUE_OFFSET                (0x0010)
+#define FW_VA_RENDER_FENCE_VALUE_SHIFT         (0)
+
+/* FW_DXVA_OOLD     FENCE_VALUE */
+#define FW_DXVA_OOLD_FENCE_VALUE_ALIGNMENT              (4)
+#define FW_DXVA_OOLD_FENCE_VALUE_TYPE           uint32_t
+#define FW_DXVA_OOLD_FENCE_VALUE_MASK           (0xFFFFFFFF)
+#define FW_DXVA_OOLD_FENCE_VALUE_LSBMASK                (0xFFFFFFFF)
+#define FW_DXVA_OOLD_FENCE_VALUE_OFFSET         (0x0008)
+#define FW_DXVA_OOLD_FENCE_VALUE_SHIFT          (0)
+
+
+/* FW_VA_RENDER     MMUPTD */
+#define FW_VA_RENDER_MMUPTD_TYPE               uint32_t
+#define FW_VA_RENDER_MMUPTD_MASK               (0xFFFFFFFF)
+#define FW_VA_RENDER_MMUPTD_OFFSET             (0x0004)
+#define FW_VA_RENDER_MMUPTD_SHIFT              (0)
+
+/* FW_VA_RENDER     BUFFER_ADDRESS */
+#define FW_VA_RENDER_BUFFER_ADDRESS_TYPE       uint32_t
+#define FW_VA_RENDER_BUFFER_ADDRESS_MASK       (0xFFFFFFFF)
+#define FW_VA_RENDER_BUFFER_ADDRESS_OFFSET     (0x0008)
+#define FW_VA_RENDER_BUFFER_ADDRESS_SHIFT      (0)
+
+/* FW_VA_RENDER     BUFFER_SIZE */
+#define FW_VA_RENDER_BUFFER_SIZE_TYPE           uint16_t
+#define FW_VA_RENDER_BUFFER_SIZE_MASK           (0x0FFF)
+#define FW_VA_RENDER_BUFFER_SIZE_OFFSET         (0x0002)
+#define FW_VA_RENDER_BUFFER_SIZE_SHIFT          (0)
+
+/* FW_VA_RENDER            FLAGS */
+#define FW_VA_RENDER_FLAGS_TYPE                 uint32_t
+#define FW_VA_RENDER_FLAGS_MASK                 (0xFFFFFFFF)
+#define FW_VA_RENDER_FLAGS_OFFSET               (0x001C)
+#define FW_VA_RENDER_FLAGS_SHIFT                (0)
+
+/* FW_DEVA_DECODE     MMUPTD */
+#define FW_VA_DECODE_MMUPTD_TYPE              uint32_t
+#define FW_VA_DECODE_MMUPTD_MASK              (0xFFFFFF00)
+#define FW_VA_DECODE_MMUPTD_OFFSET            (0x000C)
+#define FW_VA_DECODE_MMUPTD_SHIFT             (0)
+
+/* FW_DEVA_DECODE     MSG_ID */
+#define FW_VA_DECODE_MSG_ID_TYPE              uint16_t
+#define FW_VA_DECODE_MSG_ID_MASK              (0xFFFF)
+#define FW_VA_DECODE_MSG_ID_OFFSET            (0x0002)
+#define FW_VA_DECODE_MSG_ID_SHIFT             (0)
+
+/* FW_DEVA_DECODE     FLAGS */
+#define FW_DEVA_DECODE_FLAGS_TYPE               uint16_t
+#define FW_DEVA_DECODE_FLAGS_MASK               (0xFFFF)
+#define FW_DEVA_DECODE_FLAGS_OFFSET             (0x0004)
+#define FW_DEVA_DECODE_FLAGS_SHIFT              (0)
+
+#define FW_DEVA_INVALIDATE_MMU                 (0x00000010)
+
+/* FW_DEVA_CMD_COMPLETED     MSG_ID */
+#define FW_VA_CMD_COMPLETED_MSG_ID_TYPE               uint16_t
+#define FW_VA_CMD_COMPLETED_MSG_ID_MASK               (0xFFFF)
+#define FW_VA_CMD_COMPLETED_MSG_ID_OFFSET             (0x0002)
+#define FW_VA_CMD_COMPLETED_MSG_ID_SHIFT              (0)
+
+/* FW_DEVA_CMD_FAILED     MSG_ID */
+#define FW_DEVA_CMD_FAILED_MSG_ID_TYPE          uint16_t
+#define FW_DEVA_CMD_FAILED_MSG_ID_MASK          (0xFFFF)
+#define FW_DEVA_CMD_FAILED_MSG_ID_OFFSET                (0x0002)
+#define FW_DEVA_CMD_FAILED_MSG_ID_SHIFT         (0)
+
+/* FW_DEVA_CMD_FAILED     FLAGS */
+#define FW_DEVA_CMD_FAILED_FLAGS_TYPE           uint32_t
+#define FW_DEVA_CMD_FAILED_FLAGS_MASK           (0xFFFFFFFF)
+#define FW_DEVA_CMD_FAILED_FLAGS_OFFSET         (0x0004)
+#define FW_DEVA_CMD_FAILED_FLAGS_SHIFT          (0)
+
+/* FW_DXVA_DEBLOCK     MSG_SIZE */
+#define FW_DXVA_DEBLOCK_MSG_SIZE_ALIGNMENT              (1)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_TYPE           uint8_t
+#define FW_DXVA_DEBLOCK_MSG_SIZE_MASK           (0xFF)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_LSBMASK                (0xFF)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_OFFSET         (0x0000)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_SHIFT          (0)
+
+/* FW_DXVA_DEBLOCK     ID */
+#define FW_DXVA_DEBLOCK_ID_ALIGNMENT            (1)
+#define FW_DXVA_DEBLOCK_ID_TYPE         uint8_t
+#define FW_DXVA_DEBLOCK_ID_MASK         (0xFF)
+#define FW_DXVA_DEBLOCK_ID_LSBMASK              (0xFF)
+#define FW_DXVA_DEBLOCK_ID_OFFSET               (0x0001)
+#define FW_DXVA_DEBLOCK_ID_SHIFT                (0)
+
+/* FW_DXVA_DEBLOCK     FENCE_VALUE */
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_START_BIT          0
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_END_BIT            15
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_ALIGNMENT          (4)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_TYPE               uint16_t
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_MASK               (0xFFFF)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_LSBMASK            (0xFFFF)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_OFFSET             (0x0008)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_SHIFT              (0)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_SIGNED_FIELD       (0)
+
+/* FW_VA_HOST_BE_OPP MESSAGE */
+/* FW_VA_HOST_BE_OPP     FENCE_VALUE */
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_ALIGNMENT           (4)
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_TYPE                uint16_t
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_MASK                (0xFFFF)
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_LSBMASK             (0xFFFF)
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_OFFSET              (0x0008)
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_SHIFT               (0)
+
+
+/* FW_VA_HOST_BE_OPP     MMUPTD */
+#define FW_VA_HOST_BE_OPP_MMUPTD_ALIGNMENT                (4)
+#define FW_VA_HOST_BE_OPP_MMUPTD_TYPE             uint32_t
+#define FW_VA_HOST_BE_OPP_MMUPTD_MASK             (0xFFFFFFFF)
+#define FW_VA_HOST_BE_OPP_MMUPTD_LSBMASK          (0xFFFFFFFF)
+#define FW_VA_HOST_BE_OPP_MMUPTD_OFFSET           (0x000C)
+#define FW_VA_HOST_BE_OPP_MMUPTD_SHIFT            (0)
+
+
+/* FW_DXVA_DEBLOCK     MMUPTD */
+#define FW_DXVA_DEBLOCK_MMUPTD_ALIGNMENT                (4)
+#define FW_DXVA_DEBLOCK_MMUPTD_TYPE             uint32_t
+#define FW_DXVA_DEBLOCK_MMUPTD_MASK             (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_MMUPTD_LSBMASK          (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_MMUPTD_OFFSET           (0x000C)
+#define FW_DXVA_DEBLOCK_MMUPTD_SHIFT            (0)
+
+#define FW_DXVA_OOLD_SIZE               (40)
+
+
+// FW_VA_CMD_COMPLETED     VDEBCR
+#define FW_VA_CMD_COMPLETED_VDEBCR_START_BIT           0
+#define FW_VA_CMD_COMPLETED_VDEBCR_END_BIT             31
+#define FW_VA_CMD_COMPLETED_VDEBCR_ALIGNMENT           (4)
+#define FW_VA_CMD_COMPLETED_VDEBCR_TYPE                uint32_t
+#define FW_VA_CMD_COMPLETED_VDEBCR_MASK                (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_VDEBCR_LSBMASK             (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_VDEBCR_OFFSET              (0x000C)
+#define FW_VA_CMD_COMPLETED_VDEBCR_SHIFT               (0)
+#define FW_VA_CMD_COMPLETED_VDEBCR_SIGNED_FIELD        (0)
+
+/* FW_VA_CMD_FAILED     FLAGS */
+#define FW_VA_CMD_FAILED_FLAGS_ALIGNMENT               (4)
+#define FW_VA_CMD_FAILED_FLAGS_TYPE            uint32_t
+#define FW_VA_CMD_FAILED_FLAGS_MASK            (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_FLAGS_LSBMASK         (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_FLAGS_OFFSET          (0x0004)
+#define FW_VA_CMD_FAILED_FLAGS_SHIFT           (0)
+#define FW_VA_CMD_FAILED_FLAGS_SIGNED_FIELD    (0)
+
+/* FW_VA_CMD_FAILED_NO_EC     FENCE_VALUE */
+#define FW_VA_CMD_FAILED_FENCE_VALUE_NO_EC_TYPE        uint32_t
+#define FW_VA_CMD_FAILED_FENCE_VALUE_NO_EC_MASK        (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_FENCE_VALUE_NO_EC_OFFSET      (0x0004)
+#define FW_VA_CMD_FAILED_FENCE_VALUE_NO_EC_SHIFT       (0)
+
+/* FW_VA_CMD_FAILED_NO_EC     IRQSTATUS */
+#define FW_VA_CMD_FAILED_IRQSTATUS_NO_EC_TYPE          uint32_t
+#define FW_VA_CMD_FAILED_IRQSTATUS_NO_EC_MASK          (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_IRQSTATUS_NO_EC_OFFSET        (0x0008)
+#define FW_VA_CMD_FAILED_IRQSTATUS_NO_EC_SHIFT (0)
+
+/* PANIC MESSAGE */
+// FW_VA_HW_PANIC     FENCE_VALUE
+#define FW_VA_HW_PANIC_FENCE_VALUE_START_BIT           16
+#define FW_VA_HW_PANIC_FENCE_VALUE_END_BIT             31
+#define FW_VA_HW_PANIC_FENCE_VALUE_ALIGNMENT           (2)
+#define FW_VA_HW_PANIC_FENCE_VALUE_TYPE                uint16_t
+#define FW_VA_HW_PANIC_FENCE_VALUE_MASK                (0xFFFF)
+#define FW_VA_HW_PANIC_FENCE_VALUE_LSBMASK             (0xFFFF)
+#define FW_VA_HW_PANIC_FENCE_VALUE_OFFSET              (0x0002)
+#define FW_VA_HW_PANIC_FENCE_VALUE_SHIFT               (0)
+#define FW_VA_HW_PANIC_FENCE_VALUE_SIGNED_FIELD        (0)
+
+/* FW_VA_HW_PANIC     FIRST_MB_NUM */
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_START_BIT          0
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_END_BIT            15
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_ALIGNMENT          (2)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_TYPE               uint16_t
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_MASK               (0xFFFF)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_LSBMASK            (0xFFFF)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_OFFSET             (0x0004)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_SHIFT              (0)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_SIGNED_FIELD       (0)
+
+/* FW_VA_HW_PANIC     FAULT_MB_NUM */
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_START_BIT          16
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_END_BIT            31
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_ALIGNMENT          (2)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_TYPE               uint16_t
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_MASK               (0xFFFF)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_LSBMASK            (0xFFFF)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_OFFSET             (0x0006)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_SHIFT              (0)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_SIGNED_FIELD       (0)
+
+/* FW_VA_HW_PANIC     FESTATUS */
+#define FW_VA_HW_PANIC_FESTATUS_START_BIT              0
+#define FW_VA_HW_PANIC_FESTATUS_END_BIT                31
+#define FW_VA_HW_PANIC_FESTATUS_ALIGNMENT              (4)
+#define FW_VA_HW_PANIC_FESTATUS_TYPE           uint32_t
+#define FW_VA_HW_PANIC_FESTATUS_MASK           (0xFFFFFFFF)
+#define FW_VA_HW_PANIC_FESTATUS_LSBMASK                (0xFFFFFFFF)
+#define FW_VA_HW_PANIC_FESTATUS_OFFSET         (0x0008)
+#define FW_VA_HW_PANIC_FESTATUS_SHIFT          (0)
+#define FW_VA_HW_PANIC_FESTATUS_SIGNED_FIELD   (0)
+
+/* FW_VA_HW_PANIC     BESTATUS */
+#define FW_VA_HW_PANIC_BESTATUS_START_BIT              0
+#define FW_VA_HW_PANIC_BESTATUS_END_BIT                31
+#define FW_VA_HW_PANIC_BESTATUS_ALIGNMENT              (4)
+#define FW_VA_HW_PANIC_BESTATUS_TYPE           uint32_t
+#define FW_VA_HW_PANIC_BESTATUS_MASK           (0xFFFFFFFF)
+#define FW_VA_HW_PANIC_BESTATUS_LSBMASK                (0xFFFFFFFF)
+#define FW_VA_HW_PANIC_BESTATUS_OFFSET         (0x000C)
+#define FW_VA_HW_PANIC_BESTATUS_SHIFT          (0)
+#define FW_VA_HW_PANIC_BESTATUS_SIGNED_FIELD   (0)
+
+/* FW_VA_DEBLOCK_REQUIRED MESSAGE*/
+/* FW_VA_DEBLOCK_REQUIRED     FENCE_VALUE */
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_ALIGNMENT           (2)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_TYPE                uint16_t
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_MASK                (0xFFFF)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_LSBMASK             (0xFFFF)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_OFFSET              (0x0002)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_SHIFT               (0)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_SIGNED_FIELD        (0)
+
+
+/* FW_VA_DEBLOCK_REQUIRED     CONTEXTNO_EC */
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_NO_EC_TYPE      uint32_t
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_NO_EC_MASK      (0xFFFFFFFF)
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_NO_EC_OFFSET    (0x0004)
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_NO_EC_SHIFT     (0)
+
+/* FW_VA_CONTIGUITY_WARNING MESSAGE */
+#define FW_VA_CONTIGUITY_WARNING_SIZE          (8)
+
+/* FW_VA_CONTIGUITY_WARNING     FENCE_VALUE */
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_START_BIT         16
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_END_BIT           31
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_ALIGNMENT         (2)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_TYPE              uint16_t
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_MASK              (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_LSBMASK           (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_OFFSET            (0x0002)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_SHIFT             (0)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_SIGNED_FIELD      (0)
+
+/* FW_VA_CONTIGUITY_WARNING     ID */
+#define FW_VA_CONTIGUITY_WARNING_ID_START_BIT          8
+#define FW_VA_CONTIGUITY_WARNING_ID_END_BIT            15
+#define FW_VA_CONTIGUITY_WARNING_ID_ALIGNMENT          (1)
+#define FW_VA_CONTIGUITY_WARNING_ID_TYPE               uint8_t
+#define FW_VA_CONTIGUITY_WARNING_ID_MASK               (0xFF)
+#define FW_VA_CONTIGUITY_WARNING_ID_LSBMASK            (0xFF)
+#define FW_VA_CONTIGUITY_WARNING_ID_OFFSET             (0x0001)
+#define FW_VA_CONTIGUITY_WARNING_ID_SHIFT              (0)
+#define FW_VA_CONTIGUITY_WARNING_ID_SIGNED_FIELD       (0)
+
+/* FW_VA_CONTIGUITY_WARNING     MSG_SIZE */
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_START_BIT            0
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_END_BIT              7
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_ALIGNMENT            (1)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_TYPE         uint8_t
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_MASK         (0xFF)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_LSBMASK              (0xFF)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_OFFSET               (0x0000)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_SHIFT                (0)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_SIGNED_FIELD (0)
+
+/* FW_VA_CONTIGUITY_WARNING     END_MB_NUM */
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_START_BIT          0
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_END_BIT            15
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_ALIGNMENT          (2)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_TYPE               uint16_t
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_MASK               (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_LSBMASK            (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_OFFSET             (0x0004)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_SHIFT              (0)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_SIGNED_FIELD       (0)
+
+/* FW_VA_CONTIGUITY_WARNING     BEGIN_MB_NUM */
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_START_BIT                16
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_END_BIT          31
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_ALIGNMENT                (2)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_TYPE             uint16_t
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_MASK             (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_LSBMASK          (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_OFFSET           (0x0006)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_SHIFT            (0)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_SIGNED_FIELD     (0)
+
+/* FW_DXVA_OOLD     FENCE_VALUE */
+#define FW_DXVA_OOLD_FENCE_VALUE_ALIGNMENT              (4)
+#define FW_DXVA_OOLD_FENCE_VALUE_TYPE           uint32_t
+#define FW_DXVA_OOLD_FENCE_VALUE_MASK           (0xFFFFFFFF)
+#define FW_DXVA_OOLD_FENCE_VALUE_LSBMASK                (0xFFFFFFFF)
+#define FW_DXVA_OOLD_FENCE_VALUE_OFFSET         (0x0008)
+#define FW_DXVA_OOLD_FENCE_VALUE_SHIFT          (0)
+
+/* FW_DXVA_OOLD     MMUPTD */
+#define FW_DXVA_OOLD_MMUPTD_ALIGNMENT           (4)
+#define FW_DXVA_OOLD_MMUPTD_TYPE                IMG_UINT32
+#define FW_DXVA_OOLD_MMUPTD_MASK                (0xFFFFFFFF)
+#define FW_DXVA_OOLD_MMUPTD_LSBMASK             (0xFFFFFFFF)
+#define FW_DXVA_OOLD_MMUPTD_OFFSET              (0x0004)
+#define FW_DXVA_OOLD_MMUPTD_SHIFT               (0)
+
+#define FW_VA_LAST_SLICE_OF_EXT_DMA                                         0x00001000
+
+static inline void psb_msvdx_clearirq(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       unsigned long mtx_int = 0;
+
+       PSB_DEBUG_IRQ("MSVDX: clear IRQ\n");
+
+       /* Clear MTX interrupt */
+       REGIO_WRITE_FIELD_LITE(mtx_int, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ,
+                              1);
+       PSB_WMSVDX32(mtx_int, MSVDX_INTERRUPT_CLEAR);
+}
+
+
+static inline void psb_msvdx_disableirq(struct drm_device *dev)
+{
+       /* nothing */
+}
+
+
+static inline void psb_msvdx_enableirq(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       unsigned long enables = 0;
+
+       PSB_DEBUG_IRQ("MSVDX: enable MSVDX MTX IRQ\n");
+       REGIO_WRITE_FIELD_LITE(enables, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ,
+                              1);
+       PSB_WMSVDX32(enables, MSVDX_HOST_INTERRUPT_ENABLE);
+}
+
+#define MSVDX_NEW_PMSTATE(drm_dev, msvdx_priv, new_state)              \
+do {                                                                   \
+       msvdx_priv->pmstate = new_state;                                \
+       sysfs_notify_dirent(msvdx_priv->sysfs_pmstate);                 \
+       PSB_DEBUG_PM("MSVDX: %s\n",                                     \
+               (new_state == PSB_PMSTATE_POWERUP) ? "powerup"          \
+               : ((new_state == PSB_PMSTATE_POWERDOWN) ? "powerdown"   \
+                       : "clockgated"));                               \
+} while (0)
+
+#endif
diff --git a/drivers/staging/mrst/imgv/psb_msvdxinit.c b/drivers/staging/mrst/imgv/psb_msvdxinit.c
new file mode 100644 (file)
index 0000000..64b8276
--- /dev/null
@@ -0,0 +1,1298 @@
+/**************************************************************************
+ * psb_msvdxinit.c
+ * MSVDX initialization and mtx-firmware upload
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drv.h"
+#include "psb_msvdx.h"
+#include <linux/firmware.h>
+
+#define MSVDX_REG (dev_priv->msvdx_reg)
+#define UPLOAD_FW_BY_DMA 1
+#define STACKGUARDWORD          ( 0x10101010 )
+#define MSVDX_MTX_DATA_LOCATION ( 0x82880000 )
+#define UNINITILISE_MEM        ( 0xcdcdcdcd )
+#define FIRMWAREID             ( 0x014d42ab )
+
+static uint8_t psb_rev_id;
+/*MSVDX FW header*/
+struct msvdx_fw {
+       uint32_t ver;
+       uint32_t text_size;
+       uint32_t data_size;
+       uint32_t data_location;
+};
+
+int psb_wait_for_register(struct drm_psb_private *dev_priv,
+                         uint32_t offset, uint32_t value, uint32_t enable)
+{
+       uint32_t reg_value;
+       uint32_t poll_cnt = 1000000;
+       while (poll_cnt) {
+               reg_value = PSB_RMSVDX32(offset);
+               if (value == (reg_value & enable))      /* All the bits are reset   */
+                       return 0;       /* So exit                      */
+
+               /* Wait a bit */
+               PSB_UDELAY(1);
+               poll_cnt--;
+       }
+       DRM_ERROR("MSVDX: Timeout while waiting for register %08x:"
+                 " expecting %08x (mask %08x), got %08x\n",
+                 offset, value, enable, reg_value);
+
+       return 1;
+}
+
+static int psb_poll_mtx_irq(struct drm_psb_private *dev_priv)
+{
+       int ret = 0;
+       uint32_t mtx_int = 0;
+
+       REGIO_WRITE_FIELD_LITE(mtx_int, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ,
+                              1);
+
+       ret = psb_wait_for_register(dev_priv, MSVDX_INTERRUPT_STATUS,
+                                   /* Required value */
+                                   mtx_int,
+                                   /* Enabled bits */
+                                   mtx_int);
+
+       if (ret) {
+               DRM_ERROR("MSVDX: Error Mtx did not return"
+                         " int within a resonable time\n");
+               return ret;
+       }
+
+       PSB_DEBUG_IRQ("MSVDX: Got MTX Int\n");
+
+       /* Got it so clear the bit */
+       PSB_WMSVDX32(mtx_int, MSVDX_INTERRUPT_CLEAR);
+
+       return ret;
+}
+
+static void psb_write_mtx_core_reg(struct drm_psb_private *dev_priv,
+                           const uint32_t core_reg, const uint32_t val)
+{
+       uint32_t reg = 0;
+
+       /* Put data in MTX_RW_DATA */
+       PSB_WMSVDX32(val, MSVDX_MTX_REGISTER_READ_WRITE_DATA);
+
+       /* DREADY is set to 0 and request a write */
+       reg = core_reg;
+       REGIO_WRITE_FIELD_LITE(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
+                              MTX_RNW, 0);
+       REGIO_WRITE_FIELD_LITE(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
+                              MTX_DREADY, 0);
+       PSB_WMSVDX32(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST);
+
+       psb_wait_for_register(dev_priv,
+                             MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
+                             MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,
+                             MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+}
+
+#if UPLOAD_FW_BY_DMA
+
+static void psb_get_mtx_control_from_dash(struct drm_psb_private *dev_priv)
+{
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       int count = 0;
+       uint32_t reg_val = 0;
+
+       REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_IS_SLAVE, 1);
+       REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_GPIO_IN, 0x02);
+       PSB_WMSVDX32(reg_val, MSVDX_MTX_DEBUG);
+
+       do {
+               reg_val = PSB_RMSVDX32(MSVDX_MTX_DEBUG);
+               count++;
+       } while (((reg_val & 0x18) != 0) && count < 50000);
+
+       if (count >= 50000)
+               PSB_DEBUG_GENERAL("TOPAZ: timeout in get_mtx_control_from_dash\n");
+
+       /* Save the access control register...*/
+       msvdx_priv->psb_dash_access_ctrl = PSB_RMSVDX32(MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+}
+
+static void psb_release_mtx_control_from_dash(struct drm_psb_private *dev_priv)
+{
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       /* restore access control */
+       PSB_WMSVDX32(msvdx_priv->psb_dash_access_ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+       /* release bus */
+       PSB_WMSVDX32(0x4, MSVDX_MTX_DEBUG);
+}
+
+
+
+static void psb_upload_fw(struct drm_psb_private *dev_priv,
+                         uint32_t address, const unsigned int words, int fw_sel)
+{
+       uint32_t reg_val = 0;
+       uint32_t cmd;
+       uint32_t uCountReg, offset, mmu_ptd;
+       uint32_t size = (words * 4); /* byte count */
+       uint32_t dma_channel = 0; /* Setup a Simple DMA for Ch0 */
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       PSB_DEBUG_GENERAL("MSVDX: Upload firmware by DMA\n");
+       psb_get_mtx_control_from_dash(dev_priv);
+
+       // dma transfers to/from the mtx have to be 32-bit aligned and in multiples of 32 bits
+       PSB_WMSVDX32(address, REGISTER(MTX_CORE, CR_MTX_SYSC_CDMAA));
+
+       REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, BURSTSIZE,  4); // burst size in multiples of 64 bits (allowed values are 2 or 4)
+       REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, RNW, 0);    // false means write to mtx mem, true means read from mtx mem
+       REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, ENABLE,     1);                             // begin transfer
+       REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, LENGTH,     words);         // This specifies the transfer size of the DMA operation in terms of 32-bit words
+       PSB_WMSVDX32(reg_val, REGISTER(MTX_CORE, CR_MTX_SYSC_CDMAC));
+
+       // toggle channel 0 usage between mtx and other msvdx peripherals
+       {
+               reg_val = PSB_RMSVDX32(REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_MSVDX_CONTROL, DMAC_CH0_SELECT,  0);
+               PSB_WMSVDX32(reg_val, REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+       }
+
+
+       /* Clear the DMAC Stats */
+       PSB_WMSVDX32(0 , REGISTER(DMAC, DMAC_IRQ_STAT) + dma_channel);
+
+       offset = msvdx_priv->fw->offset;
+
+       if (fw_sel)
+               offset += ((msvdx_priv->mtx_mem_size + 8192) & ~0xfff);
+
+       /* use bank 0 */
+       cmd = 0;
+       PSB_WMSVDX32(cmd, REGISTER(MSVDX_CORE, CR_MMU_BANK_INDEX));
+
+       /* Write PTD to mmu base 0*/
+       mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+       PSB_WMSVDX32(mmu_ptd, REGISTER(MSVDX_CORE, CR_MMU_DIR_LIST_BASE) + 0);
+
+       /* Invalidate */
+       reg_val = PSB_RMSVDX32(REGISTER(MSVDX_CORE, CR_MMU_CONTROL0));
+       reg_val &= ~0xf;
+       REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_MMU_CONTROL0, CR_MMU_INVALDC, 1);
+       PSB_WMSVDX32(reg_val, REGISTER(MSVDX_CORE, CR_MMU_CONTROL0));
+
+       PSB_WMSVDX32(offset, REGISTER(DMAC, DMAC_SETUP) + dma_channel);
+
+       /* Only use a single dma - assert that this is valid */
+       if ((size / 4) >= (1 << 15)) {
+               DRM_ERROR("psb: DMA size beyond limited, aboart firmware uploading\n");
+               return;
+       }
+
+
+       uCountReg = PSB_DMAC_VALUE_COUNT(PSB_DMAC_BSWAP_NO_SWAP,
+                                        0,  /* 32 bits */
+                                        PSB_DMAC_DIR_MEM_TO_PERIPH,
+                                        0,
+                                        (size / 4));
+       /* Set the number of bytes to dma*/
+       PSB_WMSVDX32(uCountReg, REGISTER(DMAC,  DMAC_COUNT) + dma_channel);
+
+       cmd = PSB_DMAC_VALUE_PERIPH_PARAM(PSB_DMAC_ACC_DEL_0, PSB_DMAC_INCR_OFF, PSB_DMAC_BURST_2);
+       PSB_WMSVDX32(cmd, REGISTER(DMAC, DMAC_PERIPH) + dma_channel);
+
+       /* Set destination port for dma */
+       cmd = 0;
+       REGIO_WRITE_FIELD(cmd, DMAC_DMAC_PERIPHERAL_ADDR, ADDR, MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET);
+       PSB_WMSVDX32(cmd, REGISTER(DMAC, DMAC_PERIPHERAL_ADDR) + dma_channel);
+
+
+       /* Finally, rewrite the count register with the enable bit set*/
+       PSB_WMSVDX32(uCountReg | DMAC_DMAC_COUNT_EN_MASK, REGISTER(DMAC, DMAC_COUNT) + dma_channel);
+
+       /* Wait for all to be done */
+       if (psb_wait_for_register(dev_priv,
+                                 REGISTER(DMAC, DMAC_IRQ_STAT) + dma_channel,
+                                 DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK,
+                                 DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK)) {
+               psb_release_mtx_control_from_dash(dev_priv);
+               return;
+       }
+
+       /* Assert that the MTX DMA port is all done aswell */
+       if (psb_wait_for_register(dev_priv, REGISTER(MTX_CORE, CR_MTX_SYSC_CDMAS0), 1, 1)) {
+               psb_release_mtx_control_from_dash(dev_priv);
+               return;
+       }
+
+       psb_release_mtx_control_from_dash(dev_priv);
+       PSB_DEBUG_GENERAL("MSVDX: Upload done\n");
+}
+
+#else
+
+static void psb_upload_fw(struct drm_psb_private *dev_priv,
+                         const uint32_t data_mem, uint32_t ram_bank_size,
+                         uint32_t address, const unsigned int words,
+                         const uint32_t * const data)
+{
+       uint32_t loop, ctrl, ram_id, addr, cur_bank = (uint32_t) ~0;
+       uint32_t access_ctrl;
+
+       PSB_DEBUG_GENERAL("MSVDX: Upload firmware by register interface\n");
+       /* Save the access control register... */
+       access_ctrl = PSB_RMSVDX32(MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+       /* Wait for MCMSTAT to become be idle 1 */
+       psb_wait_for_register(dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS,
+                             1,        /* Required Value */
+                             0xffffffff /* Enables */);
+
+       for (loop = 0; loop < words; loop++) {
+               ram_id = data_mem + (address / ram_bank_size);
+               if (ram_id != cur_bank) {
+                       addr = address >> 2;
+                       ctrl = 0;
+                       REGIO_WRITE_FIELD_LITE(ctrl,
+                                              MSVDX_MTX_RAM_ACCESS_CONTROL,
+                                              MTX_MCMID, ram_id);
+                       REGIO_WRITE_FIELD_LITE(ctrl,
+                                              MSVDX_MTX_RAM_ACCESS_CONTROL,
+                                              MTX_MCM_ADDR, addr);
+                       REGIO_WRITE_FIELD_LITE(ctrl,
+                                              MSVDX_MTX_RAM_ACCESS_CONTROL,
+                                              MTX_MCMAI, 1);
+                       PSB_WMSVDX32(ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+                       cur_bank = ram_id;
+               }
+               address += 4;
+
+               PSB_WMSVDX32(data[loop],
+                            MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);
+
+               /* Wait for MCMSTAT to become be idle 1 */
+               psb_wait_for_register(dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS,
+                                     1,        /* Required Value */
+                                     0xffffffff /* Enables */);
+       }
+       PSB_DEBUG_GENERAL("MSVDX: Upload done\n");
+
+       /* Restore the access control register... */
+       PSB_WMSVDX32(access_ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+}
+
+#endif
+
+static int psb_verify_fw(struct drm_psb_private *dev_priv,
+                        const uint32_t ram_bank_size,
+                        const uint32_t data_mem, uint32_t address,
+                        const uint32_t words, const uint32_t * const data)
+{
+       uint32_t loop, ctrl, ram_id, addr, cur_bank = (uint32_t) ~0;
+       uint32_t access_ctrl;
+       int ret = 0;
+
+       /* Save the access control register... */
+       access_ctrl = PSB_RMSVDX32(MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+       /* Wait for MCMSTAT to become be idle 1 */
+       psb_wait_for_register(dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS,
+                             1,        /* Required Value */
+                             0xffffffff /* Enables */);
+
+       for (loop = 0; loop < words; loop++) {
+               uint32_t reg_value;
+               ram_id = data_mem + (address / ram_bank_size);
+
+               if (ram_id != cur_bank) {
+                       addr = address >> 2;
+                       ctrl = 0;
+                       REGIO_WRITE_FIELD_LITE(ctrl,
+                                              MSVDX_MTX_RAM_ACCESS_CONTROL,
+                                              MTX_MCMID, ram_id);
+                       REGIO_WRITE_FIELD_LITE(ctrl,
+                                              MSVDX_MTX_RAM_ACCESS_CONTROL,
+                                              MTX_MCM_ADDR, addr);
+                       REGIO_WRITE_FIELD_LITE(ctrl,
+                                              MSVDX_MTX_RAM_ACCESS_CONTROL,
+                                              MTX_MCMAI, 1);
+                       REGIO_WRITE_FIELD_LITE(ctrl,
+                                              MSVDX_MTX_RAM_ACCESS_CONTROL,
+                                              MTX_MCMR, 1);
+
+                       PSB_WMSVDX32(ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+                       cur_bank = ram_id;
+               }
+               address += 4;
+
+               /* Wait for MCMSTAT to become be idle 1 */
+               psb_wait_for_register(dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS,
+                                     1,        /* Required Value */
+                                     0xffffffff /* Enables */);
+
+               reg_value = PSB_RMSVDX32(MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);
+               if (data[loop] != reg_value) {
+                       DRM_ERROR("psb: Firmware validation fails"
+                                 " at index=%08x\n", loop);
+                       ret = 1;
+                       break;
+               }
+       }
+
+       /* Restore the access control register... */
+       PSB_WMSVDX32(access_ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+       return ret;
+}
+
+static int msvdx_get_fw_bo(struct drm_device *dev,
+                          const struct firmware **raw, uint8_t *name)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int rc, fw_size;
+       void *ptr = NULL;
+       struct ttm_bo_kmap_obj tmp_kmap;
+       bool is_iomem;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       void *gpu_addr;
+
+       rc = request_firmware(raw, name, &dev->pdev->dev);
+       if (rc < 0) {
+               DRM_ERROR("MSVDX: %s request_firmware failed: Reason %d\n",
+                         name, rc);
+               return 1;
+       }
+
+       if ((*raw)->size < sizeof(struct msvdx_fw)) {
+               DRM_ERROR("MSVDX: %s is is not correct size(%zd)\n",
+                         name, (*raw)->size);
+               return 1;
+       }
+
+       ptr = (void *)((*raw))->data;
+
+       if (!ptr) {
+               DRM_ERROR("MSVDX: Failed to load %s\n", name);
+               return 1;
+       }
+
+       /* another sanity check... */
+       fw_size = sizeof(struct msvdx_fw) +
+                 sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->text_size +
+                 sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->data_size;
+       if ((*raw)->size < fw_size) {
+               DRM_ERROR("MSVDX: %s is is not correct size(%zd)\n",
+                         name, (*raw)->size);
+               return 1;
+       }
+
+       rc = ttm_bo_kmap(msvdx_priv->fw, 0, (msvdx_priv->fw)->num_pages, &tmp_kmap);
+       if (rc) {
+               PSB_DEBUG_GENERAL("drm_bo_kmap failed: %d\n", rc);
+               ttm_bo_unref(&msvdx_priv->fw);
+               ttm_bo_kunmap(&tmp_kmap);
+               return 1;
+       } else {
+               uint32_t *last_word;
+               gpu_addr = ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem);
+
+               memset(gpu_addr, UNINITILISE_MEM, msvdx_priv->mtx_mem_size);
+
+               memcpy(gpu_addr, ptr + sizeof(struct msvdx_fw),
+                      sizeof(uint32_t) *((struct msvdx_fw *) ptr)->text_size);
+
+               memcpy(gpu_addr + (((struct msvdx_fw *) ptr)->data_location - MSVDX_MTX_DATA_LOCATION),
+                      (void *)ptr + sizeof(struct msvdx_fw) + sizeof(uint32_t) *((struct msvdx_fw *) ptr)->text_size,
+                      sizeof(uint32_t) *((struct msvdx_fw *) ptr)->data_size);
+
+               last_word = (uint32_t *)(gpu_addr + msvdx_priv->mtx_mem_size - 4);
+               /* Write a know value to last word in mtx memory*/
+               /* Usefull for detection of stack overrun */
+               *last_word = STACKGUARDWORD;
+       }
+
+       ttm_bo_kunmap(&tmp_kmap);
+       PSB_DEBUG_GENERAL("MSVDX: releasing firmware resouces\n");
+       PSB_DEBUG_GENERAL("MSVDX: Load firmware into BO successfully\n");
+       release_firmware(*raw);
+       return rc;
+}
+
+
+static uint32_t *msvdx_get_fw(struct drm_device *dev,
+                             const struct firmware **raw, uint8_t *name)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int rc, fw_size;
+       void *ptr = NULL;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       rc = request_firmware(raw, name, &dev->pdev->dev);
+       if (rc < 0) {
+               DRM_ERROR("MSVDX: %s request_firmware failed: Reason %d\n",
+                         name, rc);
+               return NULL;
+       }
+
+       if ((*raw)->size < sizeof(struct msvdx_fw)) {
+               DRM_ERROR("MSVDX: %s is is not correct size(%zd)\n",
+                         name, (*raw)->size);
+               return NULL;
+       }
+
+       ptr = (int *)((*raw))->data;
+
+       if (!ptr) {
+               DRM_ERROR("MSVDX: Failed to load %s\n", name);
+               return NULL;
+       }
+
+       /* another sanity check... */
+       fw_size = sizeof(struct msvdx_fw) +
+                 sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->text_size +
+                 sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->data_size;
+       if ((*raw)->size < fw_size) {
+               DRM_ERROR("MSVDX: %s is is not correct size(%zd)\n",
+                         name, (*raw)->size);
+               return NULL;
+       } else if ((*raw)->size > fw_size) { /* there is ec firmware */
+               ptr += ((fw_size + 0xfff) & ~0xfff);
+               fw_size += (sizeof(struct msvdx_fw) +
+                           sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->text_size +
+                           sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->data_size);
+
+               ptr = (int *)((*raw))->data;  /* Resotre ptr to start of the firmware file */
+       }
+
+       msvdx_priv->msvdx_fw = kzalloc(fw_size, GFP_KERNEL);
+       if (msvdx_priv->msvdx_fw == NULL)
+               DRM_ERROR("MSVDX: allocate FW buffer failed\n");
+       else {
+               memcpy(msvdx_priv->msvdx_fw, ptr, fw_size);
+               msvdx_priv->msvdx_fw_size = fw_size;
+       }
+
+       PSB_DEBUG_GENERAL("MSVDX: releasing firmware resouces\n");
+       release_firmware(*raw);
+
+       return msvdx_priv->msvdx_fw;
+}
+
+int psb_setup_fw(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t ram_bank_size;
+       struct msvdx_fw *fw;
+       uint32_t *fw_ptr = NULL;
+       uint32_t *text_ptr = NULL;
+       uint32_t *data_ptr = NULL;
+       const struct firmware *raw = NULL;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+       int ec_firmware = 0, ret = 0;
+
+       /* todo : Assert the clock is on - if not turn it on to upload code */
+       PSB_DEBUG_GENERAL("MSVDX: psb_setup_fw\n");
+       PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+       /* Reset MTX */
+       PSB_WMSVDX32(MSVDX_MTX_SOFT_RESET_MTX_RESET_MASK,
+                    MSVDX_MTX_SOFT_RESET);
+
+       /* Initialses Communication controll area to 0 */
+       /*
+         if (psb_rev_id >= POULSBO_D1) {
+         PSB_DEBUG_GENERAL("MSVDX: Detected Poulsbo D1"
+         " or later revision.\n");
+         PSB_WMSVDX32(MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D1,
+         MSVDX_COMMS_OFFSET_FLAGS);
+         } else {
+         PSB_DEBUG_GENERAL("MSVDX: Detected Poulsbo D0"
+         " or earlier revision.\n");
+         PSB_WMSVDX32(MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D0,
+         MSVDX_COMMS_OFFSET_FLAGS);
+         }
+       */
+
+       PSB_WMSVDX32(FIRMWAREID, MSVDX_COMMS_FIRMWARE_ID);
+
+       PSB_WMSVDX32(0, MSVDX_COMMS_ERROR_TRIG);
+       PSB_WMSVDX32(199, MSVDX_MTX_SYSC_TIMERDIV); /* MTX_SYSC_TIMERDIV */
+       PSB_WMSVDX32(0, MSVDX_EXT_FW_ERROR_STATE); /* EXT_FW_ERROR_STATE */
+
+       PSB_WMSVDX32(0, MSVDX_COMMS_MSG_COUNTER);
+       PSB_WMSVDX32(0, MSVDX_COMMS_SIGNATURE);
+       PSB_WMSVDX32(0, MSVDX_COMMS_TO_HOST_RD_INDEX);
+       PSB_WMSVDX32(0, MSVDX_COMMS_TO_HOST_WRT_INDEX);
+       PSB_WMSVDX32(0, MSVDX_COMMS_TO_MTX_RD_INDEX);
+       PSB_WMSVDX32(0, MSVDX_COMMS_TO_MTX_WRT_INDEX);
+       PSB_WMSVDX32(0, MSVDX_COMMS_FW_STATUS);
+       PSB_WMSVDX32(DSIABLE_IDLE_GPIO_SIG | DSIABLE_Auto_CLOCK_GATING | RETURN_VDEB_DATA_IN_COMPLETION | DSIABLE_FW_WDT,
+                    MSVDX_COMMS_OFFSET_FLAGS);
+       PSB_WMSVDX32(0, MSVDX_COMMS_SIGNATURE);
+       /* read register bank size */
+       {
+               uint32_t bank_size, reg;
+               reg = PSB_RMSVDX32(MSVDX_MTX_RAM_BANK);
+               bank_size =
+                       REGIO_READ_FIELD(reg, MSVDX_MTX_RAM_BANK,
+                                        CR_MTX_RAM_BANK_SIZE);
+               ram_bank_size = (uint32_t)(1 << (bank_size + 2));
+       }
+
+       PSB_DEBUG_GENERAL("MSVDX: RAM bank size = %d bytes\n",
+                         ram_bank_size);
+
+       /* if FW already loaded from storage */
+       if (msvdx_priv->msvdx_fw)
+               fw_ptr = msvdx_priv->msvdx_fw;
+       else {
+               fw_ptr = msvdx_get_fw(dev, &raw, "msvdx_fw_mfld_DE2.0.bin");
+
+               PSB_DEBUG_GENERAL("MSVDX:load msvdx_fw_mfld_DE2.0.bin by udevd\n");
+       }
+
+       if (!fw_ptr) {
+               DRM_ERROR("MSVDX:load msvdx_fw.bin failed,is udevd running?\n");
+               ret = 1;
+               goto out;
+       }
+
+       if (!msvdx_priv->is_load) {/* Load firmware into BO */
+               PSB_DEBUG_GENERAL("MSVDX:load msvdx_fw.bin by udevd into BO\n");
+               ret = msvdx_get_fw_bo(dev, &raw, "msvdx_fw_mfld_DE2.0.bin");
+               msvdx_priv->is_load = 1;
+       }
+
+
+       fw = (struct msvdx_fw *) fw_ptr;
+
+       if (ec_firmware) {
+               fw_ptr += (((sizeof(struct msvdx_fw) + (fw->text_size + fw->data_size) * 4 + 0xfff) & ~0xfff) / sizeof(uint32_t));
+               fw = (struct msvdx_fw *) fw_ptr;
+       }
+
+       /*
+         if (fw->ver != 0x02) {
+         DRM_ERROR("psb: msvdx_fw.bin firmware version mismatch,"
+         "got version=%02x expected version=%02x\n",
+         fw->ver, 0x02);
+         ret = 1;
+         goto out;
+         }
+       */
+       text_ptr =
+               (uint32_t *)((uint8_t *) fw_ptr + sizeof(struct msvdx_fw));
+       data_ptr = text_ptr + fw->text_size;
+
+       if (fw->text_size == 2858)
+               PSB_DEBUG_GENERAL(
+                       "MSVDX: FW ver 1.00.10.0187 of SliceSwitch variant\n");
+       else if (fw->text_size == 3021)
+               PSB_DEBUG_GENERAL(
+                       "MSVDX: FW ver 1.00.10.0187 of FrameSwitch variant\n");
+       else if (fw->text_size == 2841)
+               PSB_DEBUG_GENERAL("MSVDX: FW ver 1.00.10.0788\n");
+       else if (fw->text_size == 3147)
+               PSB_DEBUG_GENERAL("MSVDX: FW ver BUILD_DXVA_FW1.00.10.1042 of SliceSwitch variant\n");
+       else if (fw->text_size == 3097)
+               PSB_DEBUG_GENERAL("MSVDX: FW ver BUILD_DXVA_FW1.00.10.0963.02.0011 of FrameSwitch variant\n");
+       else
+               PSB_DEBUG_GENERAL("MSVDX: FW ver unknown\n");
+
+
+       PSB_DEBUG_GENERAL("MSVDX: Retrieved pointers for firmware\n");
+       PSB_DEBUG_GENERAL("MSVDX: text_size: %d\n", fw->text_size);
+       PSB_DEBUG_GENERAL("MSVDX: data_size: %d\n", fw->data_size);
+       PSB_DEBUG_GENERAL("MSVDX: data_location: 0x%x\n",
+                         fw->data_location);
+       PSB_DEBUG_GENERAL("MSVDX: First 4 bytes of text: 0x%x\n",
+                         *text_ptr);
+       PSB_DEBUG_GENERAL("MSVDX: First 4 bytes of data: 0x%x\n",
+                         *data_ptr);
+
+       PSB_DEBUG_GENERAL("MSVDX: Uploading firmware\n");
+#if UPLOAD_FW_BY_DMA
+       psb_upload_fw(dev_priv, 0, msvdx_priv->mtx_mem_size / 4, ec_firmware);
+#else
+       psb_upload_fw(dev_priv, MTX_CORE_CODE_MEM, ram_bank_size,
+                     PC_START_ADDRESS - MTX_CODE_BASE, fw->text_size,
+                     text_ptr);
+       psb_upload_fw(dev_priv, MTX_CORE_DATA_MEM, ram_bank_size,
+                     fw->data_location - MTX_DATA_BASE, fw->data_size,
+                     data_ptr);
+#endif
+#if 0
+       /* todo :  Verify code upload possibly only in debug */
+       ret = psb_verify_fw(dev_priv, ram_bank_size,
+                           MTX_CORE_CODE_MEM,
+                           PC_START_ADDRESS - MTX_CODE_BASE,
+                           fw->text_size, text_ptr);
+       if (ret) {
+               /* Firmware code upload failed */
+               ret = 1;
+               goto out;
+       }
+
+       ret = psb_verify_fw(dev_priv, ram_bank_size, MTX_CORE_DATA_MEM,
+                           fw->data_location - MTX_DATA_BASE,
+                           fw->data_size, data_ptr);
+       if (ret) {
+               /* Firmware data upload failed */
+               ret = 1;
+               goto out;
+       }
+#else
+       (void)psb_verify_fw;
+#endif
+       /*      -- Set starting PC address      */
+       psb_write_mtx_core_reg(dev_priv, MTX_PC, PC_START_ADDRESS);
+
+       /*      -- Turn on the thread   */
+       PSB_WMSVDX32(MSVDX_MTX_ENABLE_MTX_ENABLE_MASK, MSVDX_MTX_ENABLE);
+
+       /* Wait for the signature value to be written back */
+       ret = psb_wait_for_register(dev_priv, MSVDX_COMMS_SIGNATURE,
+                                   MSVDX_COMMS_SIGNATURE_VALUE, /*Required value*/
+                                   0xffffffff /* Enabled bits */);
+       if (ret) {
+               DRM_ERROR("MSVDX: firmware fails to initialize.\n");
+               goto out;
+       }
+
+       PSB_DEBUG_GENERAL("MSVDX: MTX Initial indications OK\n");
+       PSB_DEBUG_GENERAL("MSVDX: MSVDX_COMMS_AREA_ADDR = %08x\n",
+                         MSVDX_COMMS_AREA_ADDR);
+#if 0
+
+       /* Send test message */
+       {
+               uint32_t msg_buf[FW_VA_DEBUG_TEST2_SIZE >> 2];
+
+               MEMIO_WRITE_FIELD(msg_buf, FW_VA_DEBUG_TEST2_MSG_SIZE,
+                                 FW_VA_DEBUG_TEST2_SIZE);
+               MEMIO_WRITE_FIELD(msg_buf, FW_VA_DEBUG_TEST2_ID,
+                                 VA_MSGID_TEST2);
+
+               ret = psb_mtx_send(dev_priv, msg_buf);
+               if (ret) {
+                       DRM_ERROR("psb: MSVDX sending fails.\n");
+                       goto out;
+               }
+
+               /* Wait for Mtx to ack this message */
+               psb_poll_mtx_irq(dev_priv);
+
+       }
+#endif
+out:
+
+       return ret;
+}
+
+
+static void psb_free_ccb(struct ttm_buffer_object **ccb)
+{
+       ttm_bo_unref(ccb);
+       *ccb = NULL;
+}
+
+/**
+ * Reset chip and disable interrupts.
+ * Return 0 success, 1 failure
+ */
+int psb_msvdx_reset(struct drm_psb_private *dev_priv)
+{
+       int ret = 0;
+
+       if (IS_PENWELL(dev_priv->dev)) {
+               int loop;
+               /* Enable Clocks */
+               PSB_DEBUG_GENERAL("Enabling clocks\n");
+               PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+               /* Always pause the MMU as the core may be still active when resetting.  It is very bad to have memory
+                  activity at the same time as a reset - Very Very bad */
+               PSB_WMSVDX32(2, MSVDX_MMU_CONTROL0);
+
+               for (loop = 0; loop < 50; loop++)
+                       ret = psb_wait_for_register(dev_priv, MSVDX_MMU_MEM_REQ, 0,
+                                                   0xff);
+               if (ret)
+                       return ret;
+       }
+       /* Issue software reset */
+       /* PSB_WMSVDX32(msvdx_sw_reset_all, MSVDX_CONTROL); */
+       PSB_WMSVDX32(MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK, MSVDX_CONTROL);
+
+       ret = psb_wait_for_register(dev_priv, MSVDX_CONTROL, 0,
+                                   MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK);
+
+       if (!ret) {
+               /* Clear interrupt enabled flag */
+               PSB_WMSVDX32(0, MSVDX_HOST_INTERRUPT_ENABLE);
+
+               /* Clear any pending interrupt flags */
+               PSB_WMSVDX32(0xFFFFFFFF, MSVDX_INTERRUPT_CLEAR);
+       }
+
+       /* mutex_destroy(&msvdx_priv->msvdx_mutex); */
+
+       return ret;
+}
+
+static int psb_allocate_ccb(struct drm_device *dev,
+                           struct ttm_buffer_object **ccb,
+                           uint32_t *base_addr, unsigned long size)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct ttm_bo_device *bdev = &dev_priv->bdev;
+       int ret;
+       struct ttm_bo_kmap_obj tmp_kmap;
+       bool is_iomem;
+
+       PSB_DEBUG_INIT("MSVDX: allocate CCB\n");
+
+       ret = ttm_buffer_object_create(bdev, size,
+                                      ttm_bo_type_kernel,
+                                      DRM_PSB_FLAG_MEM_MMU |
+                                      TTM_PL_FLAG_NO_EVICT, 0, 0, 0,
+                                      NULL, ccb);
+       if (ret) {
+               DRM_ERROR("MSVDX:failed to allocate CCB.\n");
+               *ccb = NULL;
+               return 1;
+       }
+
+       ret = ttm_bo_kmap(*ccb, 0, (*ccb)->num_pages, &tmp_kmap);
+       if (ret) {
+               PSB_DEBUG_GENERAL("ttm_bo_kmap failed ret: %d\n", ret);
+               ttm_bo_unref(ccb);
+               *ccb = NULL;
+               return 1;
+       }
+       /*
+         memset(ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem), 0,
+         RENDEC_A_SIZE);
+       */
+       memset(ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem), 0,
+              size);
+       ttm_bo_kunmap(&tmp_kmap);
+
+       *base_addr = (*ccb)->offset;
+       return 0;
+}
+
+static ssize_t psb_msvdx_pmstate_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct drm_device *drm_dev = dev_get_drvdata(dev);
+       struct drm_psb_private *dev_priv;
+       struct msvdx_private *msvdx_priv;
+       unsigned int pmstate;
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (drm_dev == NULL)
+               return 0;
+
+       dev_priv = drm_dev->dev_private;
+       msvdx_priv = dev_priv->msvdx_private;
+       pmstate = msvdx_priv->pmstate;
+
+       spin_lock_irqsave(&msvdx_priv->msvdx_lock, flags);
+       ret = snprintf(buf, 64, "%s\n",
+                      (pmstate == PSB_PMSTATE_POWERUP) ? "powerup"
+                      : ((pmstate == PSB_PMSTATE_POWERDOWN) ? "powerdown"
+                         : "clockgated"));
+       spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, flags);
+
+       return ret;
+}
+
+static DEVICE_ATTR(msvdx_pmstate, 0444, psb_msvdx_pmstate_show, NULL);
+
+static void psb_msvdx_conceal_mb(char * ec_start, char * ref_start,
+                                uint32_t start_err_mb, uint32_t end_err_mb,
+                                uint32_t pic_width_mb, uint32_t stride,
+                                uint32_t mb_width, uint32_t mb_height)
+{
+       int i, offset_start, offset_end, size, full_line_start, full_line_end, extra_line_start, extra_line_end;
+       char *src, *dst;
+
+       (void)offset_end;
+       (void)offset_start;
+
+       full_line_start = (start_err_mb / pic_width_mb) * stride * mb_height;
+       full_line_end = ((end_err_mb + 1) / pic_width_mb) * stride * mb_height;
+       extra_line_start = (start_err_mb % pic_width_mb) * mb_width;
+       extra_line_end = (end_err_mb + 1) % pic_width_mb * mb_width;
+       if (extra_line_start != 0) {
+               size = stride - extra_line_start;
+               src = ref_start + full_line_start + extra_line_start;
+               dst = ec_start + full_line_start + extra_line_start;
+               for (i = 0; i < mb_height; i++) {
+                       memcpy(dst, src, size);
+                       //memset(dst, 255, size);
+                       src += stride;
+                       dst += stride;
+               }
+               full_line_start += stride * mb_height;
+       }
+       src = ref_start + full_line_start;
+       dst = ec_start + full_line_start;
+       size =  full_line_end - full_line_start;
+       memcpy(dst, src, size);
+       //memset(dst, 255, size);
+       if (extra_line_end != 0) {
+               size = extra_line_end;
+               src = ref_start + full_line_end;
+               dst = ec_start + full_line_end;
+               for (i = 0; i < mb_height; i++) {
+                       memcpy(dst, src, size);
+                       //memset(dst, 255, size);
+                       src += stride;
+                       dst += stride;
+               }
+       }
+}
+
+
+static void psb_msvdx_error_concealment(struct work_struct *data)
+{
+       uint32_t i;
+       int ret;
+       struct msvdx_private *msvdx_priv = container_of(data, struct msvdx_private, ec_work);
+       drm_psb_msvdx_frame_info_t *ec_frame = NULL;
+       drm_psb_msvdx_frame_info_t *ref_frame = NULL;
+       static struct ttm_bo_kmap_obj ec_kmap, ref_kmap;
+       struct ttm_buffer_object *ec_bo = NULL;
+       struct ttm_buffer_object *ref_bo = NULL;
+       struct ttm_object_file *tfile = msvdx_priv->tfile;
+       drm_psb_msvdx_decode_status_t *decode_status = NULL;
+       bool is_iomem;
+       char *ec_start, *ref_start;
+
+       if (msvdx_priv->ec_fence > 0)
+               msvdx_priv->ref_pic_fence = msvdx_priv->ec_fence - 1;
+       else {
+               DRM_ERROR("Can't do error concealment for the first frame.\n");
+               return;
+       }
+
+       /*get the frame_info struct for error concealment frame*/
+       for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+               if (msvdx_priv->frame_info[i].fence == msvdx_priv->ec_fence) {
+                       ec_frame = &msvdx_priv->frame_info[i];
+                       break;
+               }
+       }
+       if (!ec_frame) {
+               DRM_ERROR("MSVDX: didn't find frame_info which matched the ec fence\n");
+               return;
+       }
+       decode_status = &ec_frame->decode_status;
+       ec_bo = ttm_buffer_object_lookup(tfile, ec_frame->handle);
+       if (unlikely(ec_bo == NULL)) {
+               printk(KERN_ERR " : Could not find buffer object for setstatus.\n");
+               return;
+       }
+       ret = ttm_bo_reserve(ec_bo, true, true, false, 0);
+       if (ret) {
+               DRM_ERROR("MSVDX ERROR CONCEALMENT: reserver failed.\n");
+               return;
+       }
+       ret = ttm_bo_kmap(ec_bo,
+                         0,
+                         (ec_frame->buffer_size +
+                          PAGE_SIZE - 1) >> PAGE_SHIFT,
+                         &ec_kmap);
+       if (ret) {
+               printk("MSVDX ERROR CONCEALMENT: ec kmap failed, %d.\n", ret);
+               return;
+       }
+       ec_start = (unsigned char *) ttm_kmap_obj_virtual(&ec_kmap,
+                       &is_iomem);
+
+       /*get the frame_info struct for reference frame*/
+       for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+               if (msvdx_priv->frame_info[i].fence == msvdx_priv->ref_pic_fence) {
+                       ref_frame = &msvdx_priv->frame_info[i];
+                       break;
+               }
+       }
+       if (!ref_frame) {
+               DRM_ERROR("MSVDX: didn't find frame_info which matched the ref fence\n");
+               return;
+       }
+       ref_bo = ttm_buffer_object_lookup(tfile, ref_frame->handle);
+       if (unlikely(ref_bo == NULL)) {
+               printk(KERN_ERR " : Could not find buffer object for setstatus.\n");
+       }
+       ret = ttm_bo_reserve(ref_bo, true, true, false, 0);
+       if (ret) {
+               DRM_ERROR("MSVDX ERROR CONCEALMENT: reserver failed.\n");
+               return;
+       }
+       ret = ttm_bo_kmap(ref_bo,
+                         0,
+                         (ref_frame->buffer_size +
+                          PAGE_SIZE - 1) >> PAGE_SHIFT,
+                         &ref_kmap);
+       if (ret) {
+               printk("MSVDX ERROR CONCEALMENT: ref kmap failed, %d.\n", ret);
+               return;
+       }
+       ref_start = (unsigned char *) ttm_kmap_obj_virtual(&ref_kmap,
+                       &is_iomem);
+
+       /*copy missing mb from ref picture to ec picture*/
+       for (i = 0; i < decode_status->num_error_slice; i++) {
+               if ((decode_status->start_error_mb_list[i] >= ec_frame->size_mb) ||
+                   (decode_status->end_error_mb_list[i] >= ec_frame->size_mb) ||
+                   (decode_status->start_error_mb_list[i] > decode_status->end_error_mb_list[i]))
+                       continue;
+               psb_msvdx_conceal_mb(ec_start, ref_start,
+                                    decode_status->start_error_mb_list[i],
+                                    decode_status->end_error_mb_list[i],
+                                    ec_frame->picture_width_mb, ec_frame->buffer_stride,
+                                    16, 16);
+               psb_msvdx_conceal_mb(ec_start + ec_frame->buffer_size * 2 / 3,
+                                    ref_start + ec_frame->buffer_size * 2 / 3,
+                                    decode_status->start_error_mb_list[i],
+                                    decode_status->end_error_mb_list[i],
+                                    ec_frame->picture_width_mb, ec_frame->buffer_stride,
+                                    16, 8);
+       }
+
+       ttm_bo_kunmap(&ec_kmap);
+       ttm_bo_kunmap(&ref_kmap);
+       ttm_bo_unreserve(ec_bo);
+       ttm_bo_unreserve(ref_bo);
+
+       if (ec_bo)
+               ttm_bo_unref(&ec_bo);
+       if (ref_bo)
+               ttm_bo_unref(&ref_bo);
+
+}
+
+int psb_msvdx_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       /* uint32_t clk_gate_ctrl = clk_enable_all; */
+       uint32_t cmd;
+       int ret;
+       struct msvdx_private *msvdx_priv;
+       /*
+               uint32_t reg_value;
+               uint32_t reg_val;
+       */
+       if (!dev_priv->msvdx_private) {
+               msvdx_priv = kmalloc(sizeof(struct msvdx_private), GFP_KERNEL);
+               if (msvdx_priv == NULL)
+                       goto err_exit;
+
+               dev_priv->msvdx_private = msvdx_priv;
+               memset(msvdx_priv, 0, sizeof(struct msvdx_private));
+
+               /* get device --> drm_device --> drm_psb_private --> msvdx_priv
+                * for psb_msvdx_pmstate_show: msvdx_pmpolicy
+                * if not pci_set_drvdata, can't get drm_device from device
+                */
+               /* pci_set_drvdata(dev->pdev, dev); */
+               if (device_create_file(&dev->pdev->dev,
+                                      &dev_attr_msvdx_pmstate))
+                       DRM_ERROR("MSVDX: could not create sysfs file\n");
+               msvdx_priv->sysfs_pmstate =
+                       sysfs_get_dirent(dev->pdev->dev.kobj.sd,
+                                       NULL, "msvdx_pmstate");
+       }
+
+       msvdx_priv = dev_priv->msvdx_private;
+       if (!msvdx_priv->ccb0) { /* one for the first time */
+               /* Initialize comand msvdx queueing */
+               INIT_LIST_HEAD(&msvdx_priv->msvdx_queue);
+               INIT_LIST_HEAD(&msvdx_priv->deblock_queue);
+               mutex_init(&msvdx_priv->msvdx_mutex);
+               spin_lock_init(&msvdx_priv->msvdx_lock);
+               /*figure out the stepping */
+               pci_read_config_byte(dev->pdev, PSB_REVID_OFFSET, &psb_rev_id);
+       }
+
+       msvdx_priv->vec_local_mem_size = VEC_LOCAL_MEM_BYTE_SIZE;
+       if (!msvdx_priv->vec_local_mem_data) {
+               msvdx_priv->vec_local_mem_data =
+                       kmalloc(msvdx_priv->vec_local_mem_size, GFP_KERNEL);
+               memset(msvdx_priv->vec_local_mem_data, 0, msvdx_priv->vec_local_mem_size);
+       }
+
+       msvdx_priv->msvdx_busy = 0;
+       msvdx_priv->msvdx_hw_busy = 1;
+
+       /* Enable Clocks */
+       PSB_DEBUG_GENERAL("Enabling clocks\n");
+       PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+       /* Issue software reset for all but core*/
+       /*
+               PSB_WMSVDX32((uint32_t) ~MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK, REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+               reg_value = PSB_RMSVDX32(REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+               PSB_WMSVDX32(0, REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+               PSB_WMSVDX32(MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK, REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+
+               reg_val = 0;
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CNT_CTRL, 0x3);
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ENABLE, 0);
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION0, 1);
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLEAR_SELECT, 1);
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLKDIV_SELECT, 7);
+               PSB_WMSVDX32(820, REGISTER( MSVDX_CORE, CR_FE_MSVDX_WDT_COMPAREMATCH ));
+               PSB_WMSVDX32(reg_val, REGISTER( MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL ));
+
+               reg_val = 0;
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CNT_CTRL, 0x7);
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ENABLE, 0);
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ACTION0, 1);
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLEAR_SELECT, 0xd);
+               REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLKDIV_SELECT, 7);
+               PSB_WMSVDX32(8200, REGISTER(MSVDX_CORE, CR_BE_MSVDX_WDT_COMPAREMATCH));
+               PSB_WMSVDX32(reg_val, REGISTER(MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL));
+       */
+       /* Enable MMU by removing all bypass bits */
+       PSB_WMSVDX32(0, MSVDX_MMU_CONTROL0);
+
+       /* move firmware loading to the place receiving first command buffer */
+
+       PSB_DEBUG_GENERAL("MSVDX: Setting up RENDEC,allocate CCB 0/1\n");
+       /* Allocate device virtual memory as required by rendec.... */
+       if (!msvdx_priv->ccb0) {
+               ret = psb_allocate_ccb(dev, &msvdx_priv->ccb0,
+                                      &msvdx_priv->base_addr0,
+                                      RENDEC_A_SIZE);
+               if (ret) {
+                       PSB_DEBUG_GENERAL("Allocate Rendec A fail\n");
+                       goto err_exit;
+               }
+       }
+
+       if (!msvdx_priv->ccb1) {
+               ret = psb_allocate_ccb(dev, &msvdx_priv->ccb1,
+                                      &msvdx_priv->base_addr1,
+                                      RENDEC_B_SIZE);
+               if (ret)
+                       goto err_exit;
+       }
+
+       if (!msvdx_priv->fw) {
+               uint32_t core_rev;
+               uint32_t fw_bo_size;
+
+               core_rev = PSB_RMSVDX32(MSVDX_CORE_REV);
+
+               if ((core_rev & 0xffffff) < 0x020000)
+                       msvdx_priv->mtx_mem_size = 16 * 1024;
+               else
+                       msvdx_priv->mtx_mem_size = 40 * 1024;
+
+               fw_bo_size =  msvdx_priv->mtx_mem_size + 4096;
+
+               PSB_DEBUG_INIT("MSVDX: MTX mem size is 0x%08xbytes  allocate firmware BO size 0x%08x\n", msvdx_priv->mtx_mem_size,
+                              fw_bo_size);
+
+               ret = ttm_buffer_object_create(&dev_priv->bdev, fw_bo_size, /* DMA may run over a page */
+                                              ttm_bo_type_kernel,
+                                              DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+                                              0, 0, 0, NULL, &msvdx_priv->fw);
+
+               if (ret) {
+                       PSB_DEBUG_GENERAL("Allocate firmware BO fail\n");
+                       goto err_exit;
+               }
+       }
+
+       PSB_DEBUG_GENERAL("MSVDX: RENDEC A: %08x RENDEC B: %08x\n",
+                         msvdx_priv->base_addr0, msvdx_priv->base_addr1);
+
+       PSB_WMSVDX32(msvdx_priv->base_addr0, MSVDX_RENDEC_BASE_ADDR0);
+       PSB_WMSVDX32(msvdx_priv->base_addr1, MSVDX_RENDEC_BASE_ADDR1);
+
+       cmd = 0;
+       REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_BUFFER_SIZE,
+                         RENDEC_BUFFER_SIZE0, RENDEC_A_SIZE / 4096);
+       REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_BUFFER_SIZE,
+                         RENDEC_BUFFER_SIZE1, RENDEC_B_SIZE / 4096);
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_BUFFER_SIZE);
+
+       if (!msvdx_priv->fw) {
+               uint32_t core_rev;
+
+               core_rev = PSB_RMSVDX32(MSVDX_CORE_REV);
+
+               if ((core_rev & 0xffffff) < 0x020000)
+                       msvdx_priv->mtx_mem_size = 16 * 1024;
+               else
+                       msvdx_priv->mtx_mem_size = 40 * 1024;
+
+               PSB_DEBUG_INIT("MSVDX: MTX mem size is 0x%08xbytes  allocate firmware BO size 0x%08x\n", msvdx_priv->mtx_mem_size,
+                              msvdx_priv->mtx_mem_size + 4096);
+
+               ret = ttm_buffer_object_create(&dev_priv->bdev, msvdx_priv->mtx_mem_size + 4096, /* DMA may run over a page */
+                                              ttm_bo_type_kernel,
+                                              DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+                                              0, 0, 0, NULL, &msvdx_priv->fw);
+
+               if (ret) {
+                       PSB_DEBUG_GENERAL("Allocate firmware BO fail\n");
+                       goto err_exit;
+               }
+       }
+
+       cmd = 0;
+       REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+                         RENDEC_DECODE_START_SIZE, 0);
+       REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+                         RENDEC_BURST_SIZE_W, 1);
+       REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+                         RENDEC_BURST_SIZE_R, 1);
+       REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+                         RENDEC_EXTERNAL_MEMORY, 1);
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTROL1);
+
+       cmd = 0x00101010;
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT0);
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT1);
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT2);
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT3);
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT4);
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT5);
+
+       cmd = 0;
+       REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL0, RENDEC_INITIALISE,
+                         1);
+       PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTROL0);
+
+       /* PSB_WMSVDX32(clk_enable_minimal, MSVDX_MAN_CLK_ENABLE); */
+       PSB_DEBUG_INIT("MSVDX:defer firmware loading to the"
+                      " place when receiving user space commands\n");
+
+       msvdx_priv->msvdx_fw_loaded = 0; /* need to load firware */
+
+       PSB_WMSVDX32(820, MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH);
+       PSB_WMSVDX32(8200, MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH);
+
+       PSB_WMSVDX32(820, MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH);
+       PSB_WMSVDX32(8200, MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH);
+
+       psb_msvdx_clearirq(dev);
+       psb_msvdx_enableirq(dev);
+
+       PSB_DEBUG_INIT("MSDVX:old clock gating disable = 0x%08x\n",
+               PSB_RVDC32(PSB_MSVDX_CLOCKGATING));
+
+       {
+               cmd = 0;
+               cmd = PSB_RMSVDX32(MSVDX_VEC_SHIFTREG_CONTROL); /* VEC_SHIFTREG_CONTROL */
+               REGIO_WRITE_FIELD(cmd,
+                                 VEC_SHIFTREG_CONTROL,
+                                 SR_MASTER_SELECT,
+                                 1);  /* Host */
+               PSB_WMSVDX32(cmd, MSVDX_VEC_SHIFTREG_CONTROL);
+       }
+
+#if 0
+       ret = psb_setup_fw(dev);
+       if (ret)
+               goto err_exit;
+       /* Send Initialisation message to firmware */
+       if (0) {
+               uint32_t msg_init[FW_VA_INIT_SIZE >> 2];
+               MEMIO_WRITE_FIELD(msg_init, FWRK_GENMSG_SIZE,
+                                 FW_VA_INIT_SIZE);
+               MEMIO_WRITE_FIELD(msg_init, FWRK_GENMSG_ID, VA_MSGID_INIT);
+
+               /* Need to set this for all but A0 */
+               MEMIO_WRITE_FIELD(msg_init, FW_VA_INIT_GLOBAL_PTD,
+                                 psb_get_default_pd_addr(dev_priv->mmu));
+
+               ret = psb_mtx_send(dev_priv, msg_init);
+               if (ret)
+                       goto err_exit;
+
+               psb_poll_mtx_irq(dev_priv);
+       }
+#endif
+
+       return 0;
+
+err_exit:
+       DRM_ERROR("MSVDX: initialization failed\n");
+       if (msvdx_priv && msvdx_priv->ccb0)
+               psb_free_ccb(&msvdx_priv->ccb0);
+       if (msvdx_priv && msvdx_priv->ccb1)
+               psb_free_ccb(&msvdx_priv->ccb1);
+       kfree(dev_priv->msvdx_private);
+
+       return 1;
+}
+
+int psb_msvdx_uninit(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+       /* Reset MSVDX chip */
+       psb_msvdx_reset(dev_priv);
+
+       /* PSB_WMSVDX32 (clk_enable_minimal, MSVDX_MAN_CLK_ENABLE); */
+       PSB_DEBUG_INIT("MSVDX:set the msvdx clock to 0\n");
+       PSB_WMSVDX32(0, MSVDX_MAN_CLK_ENABLE);
+
+       if (NULL == msvdx_priv) {
+               DRM_ERROR("MSVDX: psb_msvdx_uninit: msvdx_priv is NULL!\n");
+               return -1;
+       }
+
+       if (msvdx_priv->ccb0)
+               psb_free_ccb(&msvdx_priv->ccb0);
+       if (msvdx_priv->ccb1)
+               psb_free_ccb(&msvdx_priv->ccb1);
+       if (msvdx_priv->msvdx_fw)
+               kfree(msvdx_priv->msvdx_fw
+                    );
+       if (msvdx_priv->vec_local_mem_data)
+               kfree(msvdx_priv->vec_local_mem_data);
+
+       if (msvdx_priv) {
+               /* pci_set_drvdata(dev->pdev, NULL); */
+               device_remove_file(&dev->pdev->dev, &dev_attr_msvdx_pmstate);
+               sysfs_put(msvdx_priv->sysfs_pmstate);
+               msvdx_priv->sysfs_pmstate = NULL;
+
+               kfree(msvdx_priv);
+               dev_priv->msvdx_private = NULL;
+       }
+
+       return 0;
+}
diff --git a/drivers/staging/mrst/imgv/psb_ttm_fence.c b/drivers/staging/mrst/imgv/psb_ttm_fence.c
new file mode 100644 (file)
index 0000000..c2de5a3
--- /dev/null
@@ -0,0 +1,604 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "psb_ttm_fence_api.h"
+#include "psb_ttm_fence_driver.h"
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include <drm/drmP.h>
+
+/*
+ * Simple implementation for now.
+ */
+
+static void ttm_fence_lockup(struct ttm_fence_object *fence, uint32_t mask)
+{
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+
+       printk(KERN_ERR "GPU lockup dectected on engine %u "
+              "fence type 0x%08x\n",
+              (unsigned int)fence->fence_class, (unsigned int)mask);
+       /*
+        * Give engines some time to idle?
+        */
+
+       write_lock(&fc->lock);
+       ttm_fence_handler(fence->fdev, fence->fence_class,
+                         fence->sequence, mask, -EBUSY);
+       write_unlock(&fc->lock);
+}
+
+/*
+ * Convenience function to be called by fence::wait methods that
+ * need polling.
+ */
+
+static int ttm_fence_wait_polling(struct ttm_fence_object *fence, bool lazy,
+                          bool interruptible, uint32_t mask)
+{
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+       const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+       uint32_t count = 0;
+       int ret;
+       unsigned long end_jiffies = fence->timeout_jiffies;
+
+       DECLARE_WAITQUEUE(entry, current);
+       add_wait_queue(&fc->fence_queue, &entry);
+
+       ret = 0;
+
+       for (;;) {
+               __set_current_state((interruptible) ?
+                                   TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+               if (ttm_fence_object_signaled(fence, mask))
+                       break;
+               if (time_after_eq(jiffies, end_jiffies)) {
+                       if (driver->lockup)
+                               driver->lockup(fence, mask);
+                       else
+                               ttm_fence_lockup(fence, mask);
+                       continue;
+               }
+               if (lazy)
+                       schedule_timeout(1);
+               else if ((++count & 0x0F) == 0) {
+                       __set_current_state(TASK_RUNNING);
+                       schedule();
+                       __set_current_state((interruptible) ?
+                                           TASK_INTERRUPTIBLE :
+                                           TASK_UNINTERRUPTIBLE);
+               }
+               if (interruptible && signal_pending(current)) {
+                       ret = -ERESTART;
+                       break;
+               }
+       }
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&fc->fence_queue, &entry);
+       return ret;
+}
+
+/*
+ * Typically called by the IRQ handler.
+ */
+
+void ttm_fence_handler(struct ttm_fence_device *fdev, uint32_t fence_class,
+                      uint32_t sequence, uint32_t type, uint32_t error)
+{
+       int wake = 0;
+       uint32_t diff;
+       uint32_t relevant_type;
+       uint32_t new_type;
+       struct ttm_fence_class_manager *fc = &fdev->fence_class[fence_class];
+       const struct ttm_fence_driver *driver = ttm_fence_driver_from_dev(fdev);
+       struct list_head *head;
+       struct ttm_fence_object *fence, *next;
+       bool found = false;
+
+       if (list_empty(&fc->ring))
+               return;
+
+       list_for_each_entry(fence, &fc->ring, ring) {
+               diff = (sequence - fence->sequence) & fc->sequence_mask;
+               if (diff > fc->wrap_diff) {
+                       found = true;
+                       break;
+               }
+       }
+
+       fc->waiting_types &= ~type;
+       head = (found) ? &fence->ring : &fc->ring;
+
+       list_for_each_entry_safe_reverse(fence, next, head, ring) {
+               if (&fence->ring == &fc->ring)
+                       break;
+
+               DRM_DEBUG("Fence 0x%08lx, sequence 0x%08x, type 0x%08x\n",
+                         (unsigned long)fence, fence->sequence,
+                         fence->fence_type);
+
+               if (error) {
+                       fence->info.error = error;
+                       fence->info.signaled_types = fence->fence_type;
+                       list_del_init(&fence->ring);
+                       wake = 1;
+                       break;
+               }
+
+               relevant_type = type & fence->fence_type;
+               new_type = (fence->info.signaled_types | relevant_type) ^
+                          fence->info.signaled_types;
+
+               if (new_type) {
+                       fence->info.signaled_types |= new_type;
+                       DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n",
+                                 (unsigned long)fence,
+                                 fence->info.signaled_types);
+
+                       if (unlikely(driver->signaled))
+                               driver->signaled(fence);
+
+                       if (driver->needed_flush)
+                               fc->pending_flush |=
+                                       driver->needed_flush(fence);
+
+                       if (new_type & fence->waiting_types)
+                               wake = 1;
+               }
+
+               fc->waiting_types |=
+                       fence->waiting_types & ~fence->info.signaled_types;
+
+               if (!(fence->fence_type & ~fence->info.signaled_types)) {
+                       DRM_DEBUG("Fence completely signaled 0x%08lx\n",
+                                 (unsigned long)fence);
+                       list_del_init(&fence->ring);
+               }
+       }
+
+       /*
+        * Reinstate lost waiting types.
+        */
+
+       if ((fc->waiting_types & type) != type) {
+               head = head->prev;
+               list_for_each_entry(fence, head, ring) {
+                       if (&fence->ring == &fc->ring)
+                               break;
+                       diff =
+                               (fc->highest_waiting_sequence -
+                                fence->sequence) & fc->sequence_mask;
+                       if (diff > fc->wrap_diff)
+                               break;
+
+                       fc->waiting_types |=
+                               fence->waiting_types & ~fence->info.signaled_types;
+               }
+       }
+
+       if (wake)
+               wake_up_all(&fc->fence_queue);
+}
+
+static void ttm_fence_unring(struct ttm_fence_object *fence)
+{
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+       unsigned long irq_flags;
+
+       write_lock_irqsave(&fc->lock, irq_flags);
+       list_del_init(&fence->ring);
+       write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+bool ttm_fence_object_signaled(struct ttm_fence_object *fence, uint32_t mask)
+{
+       unsigned long flags;
+       bool signaled;
+       const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+
+       mask &= fence->fence_type;
+       read_lock_irqsave(&fc->lock, flags);
+       signaled = (mask & fence->info.signaled_types) == mask;
+       read_unlock_irqrestore(&fc->lock, flags);
+       if (!signaled && driver->poll) {
+               write_lock_irqsave(&fc->lock, flags);
+               driver->poll(fence->fdev, fence->fence_class, mask);
+               signaled = (mask & fence->info.signaled_types) == mask;
+               write_unlock_irqrestore(&fc->lock, flags);
+       }
+       return signaled;
+}
+
+int ttm_fence_object_flush(struct ttm_fence_object *fence, uint32_t type)
+{
+       const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+       unsigned long irq_flags;
+       uint32_t saved_pending_flush;
+       uint32_t diff;
+       bool call_flush;
+
+       if (type & ~fence->fence_type) {
+               DRM_ERROR("Flush trying to extend fence type, "
+                         "0x%x, 0x%x\n", type, fence->fence_type);
+               return -EINVAL;
+       }
+
+       write_lock_irqsave(&fc->lock, irq_flags);
+       fence->waiting_types |= type;
+       fc->waiting_types |= fence->waiting_types;
+       diff = (fence->sequence - fc->highest_waiting_sequence) &
+              fc->sequence_mask;
+
+       if (diff < fc->wrap_diff)
+               fc->highest_waiting_sequence = fence->sequence;
+
+       /*
+        * fence->waiting_types has changed. Determine whether
+        * we need to initiate some kind of flush as a result of this.
+        */
+
+       saved_pending_flush = fc->pending_flush;
+       if (driver->needed_flush)
+               fc->pending_flush |= driver->needed_flush(fence);
+
+       if (driver->poll)
+               driver->poll(fence->fdev, fence->fence_class,
+                            fence->waiting_types);
+
+       call_flush = (fc->pending_flush != 0);
+       write_unlock_irqrestore(&fc->lock, irq_flags);
+
+       if (call_flush && driver->flush)
+               driver->flush(fence->fdev, fence->fence_class);
+
+       return 0;
+}
+
+/*
+ * Make sure old fence objects are signaled before their fence sequences are
+ * wrapped around and reused.
+ */
+
+static void ttm_fence_flush_old(struct ttm_fence_device *fdev,
+                        uint32_t fence_class, uint32_t sequence)
+{
+       struct ttm_fence_class_manager *fc = &fdev->fence_class[fence_class];
+       struct ttm_fence_object *fence;
+       unsigned long irq_flags;
+       const struct ttm_fence_driver *driver = fdev->driver;
+       bool call_flush;
+
+       uint32_t diff;
+
+       write_lock_irqsave(&fc->lock, irq_flags);
+
+       list_for_each_entry_reverse(fence, &fc->ring, ring) {
+               diff = (sequence - fence->sequence) & fc->sequence_mask;
+               if (diff <= fc->flush_diff)
+                       break;
+
+               fence->waiting_types = fence->fence_type;
+               fc->waiting_types |= fence->fence_type;
+
+               if (driver->needed_flush)
+                       fc->pending_flush |= driver->needed_flush(fence);
+       }
+
+       if (driver->poll)
+               driver->poll(fdev, fence_class, fc->waiting_types);
+
+       call_flush = (fc->pending_flush != 0);
+       write_unlock_irqrestore(&fc->lock, irq_flags);
+
+       if (call_flush && driver->flush)
+               driver->flush(fdev, fence->fence_class);
+
+       /*
+        * FIXME: Shold we implement a wait here for really old fences?
+        */
+
+}
+
+int ttm_fence_object_wait(struct ttm_fence_object *fence,
+                         bool lazy, bool interruptible, uint32_t mask)
+{
+       const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+       int ret = 0;
+       unsigned long timeout;
+       unsigned long cur_jiffies;
+       unsigned long to_jiffies;
+
+       if (mask & ~fence->fence_type) {
+               DRM_ERROR("Wait trying to extend fence type"
+                         " 0x%08x 0x%08x\n", mask, fence->fence_type);
+               BUG();
+               return -EINVAL;
+       }
+
+       if (driver->wait)
+               return driver->wait(fence, lazy, interruptible, mask);
+
+       ttm_fence_object_flush(fence, mask);
+retry:
+       if (!driver->has_irq ||
+           driver->has_irq(fence->fdev, fence->fence_class, mask)) {
+
+               cur_jiffies = jiffies;
+               to_jiffies = fence->timeout_jiffies;
+
+               timeout = (time_after(to_jiffies, cur_jiffies)) ?
+                         to_jiffies - cur_jiffies : 1;
+
+               if (interruptible)
+                       ret = wait_event_interruptible_timeout
+                             (fc->fence_queue,
+                              ttm_fence_object_signaled(fence, mask), timeout);
+               else
+                       ret = wait_event_timeout
+                             (fc->fence_queue,
+                              ttm_fence_object_signaled(fence, mask), timeout);
+
+               if (unlikely(ret == -ERESTARTSYS))
+                       return -ERESTART;
+
+               if (unlikely(ret == 0)) {
+                       if (driver->lockup)
+                               driver->lockup(fence, mask);
+                       else
+                               ttm_fence_lockup(fence, mask);
+                       goto retry;
+               }
+
+               return 0;
+       }
+
+       return ttm_fence_wait_polling(fence, lazy, interruptible, mask);
+}
+
+static int ttm_fence_object_emit(struct ttm_fence_object *fence, uint32_t fence_flags,
+                         uint32_t fence_class, uint32_t type)
+{
+       const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+       unsigned long flags;
+       uint32_t sequence;
+       unsigned long timeout;
+       int ret;
+
+       ttm_fence_unring(fence);
+       ret = driver->emit(fence->fdev,
+                          fence_class, fence_flags, &sequence, &timeout);
+       if (ret)
+               return ret;
+
+       write_lock_irqsave(&fc->lock, flags);
+       fence->fence_class = fence_class;
+       fence->fence_type = type;
+       fence->waiting_types = 0;
+       fence->info.signaled_types = 0;
+       fence->info.error = 0;
+       fence->sequence = sequence;
+       fence->timeout_jiffies = timeout;
+       if (list_empty(&fc->ring))
+               fc->highest_waiting_sequence = sequence - 1;
+       list_add_tail(&fence->ring, &fc->ring);
+       fc->latest_queued_sequence = sequence;
+       write_unlock_irqrestore(&fc->lock, flags);
+       return 0;
+}
+
+int ttm_fence_object_init(struct ttm_fence_device *fdev,
+                         uint32_t fence_class,
+                         uint32_t type,
+                         uint32_t create_flags,
+                         void (*destroy)(struct ttm_fence_object *),
+                         struct ttm_fence_object *fence)
+{
+       int ret = 0;
+
+       kref_init(&fence->kref);
+       fence->fence_class = fence_class;
+       fence->fence_type = type;
+       fence->info.signaled_types = 0;
+       fence->waiting_types = 0;
+       fence->sequence = 0;
+       fence->info.error = 0;
+       fence->fdev = fdev;
+       fence->destroy = destroy;
+       INIT_LIST_HEAD(&fence->ring);
+       atomic_inc(&fdev->count);
+
+       if (create_flags & TTM_FENCE_FLAG_EMIT) {
+               ret = ttm_fence_object_emit(fence, create_flags,
+                                           fence->fence_class, type);
+       }
+
+       return ret;
+}
+
+int ttm_fence_object_create(struct ttm_fence_device *fdev,
+                           uint32_t fence_class,
+                           uint32_t type,
+                           uint32_t create_flags,
+                           struct ttm_fence_object **c_fence)
+{
+       struct ttm_fence_object *fence;
+       int ret;
+
+       ret = ttm_mem_global_alloc(fdev->mem_glob,
+                                  sizeof(*fence),
+                                  false,
+                                  false);
+       if (unlikely(ret != 0)) {
+               printk(KERN_ERR "Out of memory creating fence object\n");
+               return ret;
+       }
+
+       fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+       if (!fence) {
+               printk(KERN_ERR "Out of memory creating fence object\n");
+               ttm_mem_global_free(fdev->mem_glob, sizeof(*fence));
+               return -ENOMEM;
+       }
+
+       ret = ttm_fence_object_init(fdev, fence_class, type,
+                                   create_flags, NULL, fence);
+       if (ret) {
+               ttm_fence_object_unref(&fence);
+               return ret;
+       }
+       *c_fence = fence;
+
+       return 0;
+}
+
+static void ttm_fence_object_destroy(struct kref *kref)
+{
+       struct ttm_fence_object *fence =
+               container_of(kref, struct ttm_fence_object, kref);
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+       unsigned long irq_flags;
+
+       write_lock_irqsave(&fc->lock, irq_flags);
+       list_del_init(&fence->ring);
+       write_unlock_irqrestore(&fc->lock, irq_flags);
+
+       atomic_dec(&fence->fdev->count);
+       if (fence->destroy)
+               fence->destroy(fence);
+       else {
+               ttm_mem_global_free(fence->fdev->mem_glob,
+                                   sizeof(*fence));
+               kfree(fence);
+       }
+}
+
+void ttm_fence_device_release(struct ttm_fence_device *fdev)
+{
+       kfree(fdev->fence_class);
+}
+
+int
+ttm_fence_device_init(int num_classes,
+                     struct ttm_mem_global *mem_glob,
+                     struct ttm_fence_device *fdev,
+                     const struct ttm_fence_class_init *init,
+                     bool replicate_init,
+                     const struct ttm_fence_driver *driver)
+{
+       struct ttm_fence_class_manager *fc;
+       const struct ttm_fence_class_init *fci;
+       int i;
+
+       fdev->mem_glob = mem_glob;
+       fdev->fence_class = kzalloc(num_classes *
+                                   sizeof(*fdev->fence_class), GFP_KERNEL);
+
+       if (unlikely(!fdev->fence_class))
+               return -ENOMEM;
+
+       fdev->num_classes = num_classes;
+       atomic_set(&fdev->count, 0);
+       fdev->driver = driver;
+
+       for (i = 0; i < fdev->num_classes; ++i) {
+               fc = &fdev->fence_class[i];
+               fci = &init[(replicate_init) ? 0 : i];
+
+               fc->wrap_diff = fci->wrap_diff;
+               fc->flush_diff = fci->flush_diff;
+               fc->sequence_mask = fci->sequence_mask;
+
+               rwlock_init(&fc->lock);
+               INIT_LIST_HEAD(&fc->ring);
+               init_waitqueue_head(&fc->fence_queue);
+       }
+
+       return 0;
+}
+
+struct ttm_fence_info ttm_fence_get_info(struct ttm_fence_object *fence) {
+       struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+       struct ttm_fence_info tmp;
+       unsigned long irq_flags;
+
+       read_lock_irqsave(&fc->lock, irq_flags);
+       tmp = fence->info;
+       read_unlock_irqrestore(&fc->lock, irq_flags);
+
+       return tmp;
+}
+
+void ttm_fence_object_unref(struct ttm_fence_object **p_fence)
+{
+       struct ttm_fence_object *fence = *p_fence;
+
+       *p_fence = NULL;
+       (void)kref_put(&fence->kref, &ttm_fence_object_destroy);
+}
+
+/*
+ * Placement / BO sync object glue.
+ */
+
+bool ttm_fence_sync_obj_signaled(void *sync_obj, void *sync_arg)
+{
+       struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+       uint32_t fence_types = (uint32_t)(unsigned long)sync_arg;
+
+       return ttm_fence_object_signaled(fence, fence_types);
+}
+
+int ttm_fence_sync_obj_wait(void *sync_obj, void *sync_arg,
+                           bool lazy, bool interruptible)
+{
+       struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+       uint32_t fence_types = (uint32_t)(unsigned long)sync_arg;
+
+       return ttm_fence_object_wait(fence, lazy, interruptible, fence_types);
+}
+
+int ttm_fence_sync_obj_flush(void *sync_obj, void *sync_arg)
+{
+       struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+       uint32_t fence_types = (uint32_t)(unsigned long)sync_arg;
+
+       return ttm_fence_object_flush(fence, fence_types);
+}
+
+void ttm_fence_sync_obj_unref(void **sync_obj)
+{
+       ttm_fence_object_unref((struct ttm_fence_object **)sync_obj);
+}
+
+void *ttm_fence_sync_obj_ref(void *sync_obj)
+{
+       return (void *)
+              ttm_fence_object_ref((struct ttm_fence_object *)sync_obj);
+}
diff --git a/drivers/staging/mrst/imgv/psb_ttm_fence_api.h b/drivers/staging/mrst/imgv/psb_ttm_fence_api.h
new file mode 100644 (file)
index 0000000..3954f3b
--- /dev/null
@@ -0,0 +1,271 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+#ifndef _TTM_FENCE_API_H_
+#define _TTM_FENCE_API_H_
+
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#define TTM_FENCE_FLAG_EMIT (1 << 0)
+#define TTM_FENCE_TYPE_EXE  (1 << 0)
+
+struct ttm_fence_device;
+
+/**
+ * struct ttm_fence_info
+ *
+ * @fence_class:    The fence class.
+ * @fence_type:     Bitfield indicating types for this fence.
+ * @signaled_types: Bitfield indicating which types are signaled.
+ * @error:          Last error reported from the device.
+ *
+ * Used as output from the ttm_fence_get_info
+ */
+
+struct ttm_fence_info {
+       uint32_t signaled_types;
+       uint32_t error;
+};
+
+/**
+ * struct ttm_fence_object
+ *
+ * @fdev:            Pointer to the fence device struct.
+ * @kref:            Holds the reference count of this fence object.
+ * @ring:            List head used for the circular list of not-completely
+ *                   signaled fences.
+ * @info:            Data for fast retrieval using the ttm_fence_get_info()
+ * function.
+ * @timeout_jiffies: Absolute jiffies value indicating when this fence
+ *                   object times out and, if waited on, calls ttm_fence_lockup
+ *                   to check for and resolve a GPU lockup.
+ * @sequence:        Fence sequence number.
+ * @waiting_types:   Types currently waited on.
+ * @destroy:         Called to free the fence object, when its refcount has
+ *                   reached zero. If NULL, kfree is used.
+ *
+ * This struct is provided in the driver interface so that drivers can
+ * derive from it and create their own fence implementation. All members
+ * are private to the fence implementation and the fence driver callbacks.
+ * Otherwise a driver may access the derived object using container_of().
+ */
+
+struct ttm_fence_object {
+       struct ttm_fence_device *fdev;
+       struct kref kref;
+       uint32_t fence_class;
+       uint32_t fence_type;
+
+       /*
+        * The below fields are protected by the fence class
+        * manager spinlock.
+        */
+
+       struct list_head ring;
+       struct ttm_fence_info info;
+       unsigned long timeout_jiffies;
+       uint32_t sequence;
+       uint32_t waiting_types;
+       void (*destroy)(struct ttm_fence_object *);
+};
+
+/**
+ * ttm_fence_object_init
+ *
+ * @fdev: Pointer to a struct ttm_fence_device.
+ * @fence_class: Fence class for this fence.
+ * @type: Fence type for this fence.
+ * @create_flags: Flags indicating varios actions at init time. At this point
+ * there's only TTM_FENCE_FLAG_EMIT, which triggers a sequence emission to
+ * the command stream.
+ * @destroy: Destroy function. If NULL, kfree() is used.
+ * @fence: The struct ttm_fence_object to initialize.
+ *
+ * Initialize a pre-allocated fence object. This function, together with the
+ * destroy function makes it possible to derive driver-specific fence objects.
+ */
+
+extern int
+ttm_fence_object_init(struct ttm_fence_device *fdev,
+                     uint32_t fence_class,
+                     uint32_t type,
+                     uint32_t create_flags,
+                     void (*destroy)(struct ttm_fence_object *fence),
+                     struct ttm_fence_object *fence);
+
+/**
+ * ttm_fence_object_create
+ *
+ * @fdev: Pointer to a struct ttm_fence_device.
+ * @fence_class: Fence class for this fence.
+ * @type: Fence type for this fence.
+ * @create_flags: Flags indicating varios actions at init time. At this point
+ * there's only TTM_FENCE_FLAG_EMIT, which triggers a sequence emission to
+ * the command stream.
+ * @c_fence: On successful termination, *(@c_fence) will point to the created
+ * fence object.
+ *
+ * Create and initialize a struct ttm_fence_object. The destroy function will
+ * be set to kfree().
+ */
+
+extern int
+ttm_fence_object_create(struct ttm_fence_device *fdev,
+                       uint32_t fence_class,
+                       uint32_t type,
+                       uint32_t create_flags,
+                       struct ttm_fence_object **c_fence);
+
+/**
+ * ttm_fence_object_wait
+ *
+ * @fence: The fence object to wait on.
+ * @lazy: Allow sleeps to reduce the cpu-usage if polling.
+ * @interruptible: Sleep interruptible when waiting.
+ * @type_mask: Wait for the given type_mask to signal.
+ *
+ * Wait for a fence to signal the given type_mask. The function will
+ * perform a fence_flush using type_mask. (See ttm_fence_object_flush).
+ *
+ * Returns
+ * -ERESTART if interrupted by a signal.
+ * May return driver-specific error codes if timed-out.
+ */
+
+extern int
+ttm_fence_object_wait(struct ttm_fence_object *fence,
+                     bool lazy, bool interruptible, uint32_t type_mask);
+
+/**
+ * ttm_fence_object_flush
+ *
+ * @fence: The fence object to flush.
+ * @flush_mask: Fence types to flush.
+ *
+ * Make sure that the given fence eventually signals the
+ * types indicated by @flush_mask. Note that this may or may not
+ * map to a CPU or GPU flush.
+ */
+
+extern int
+ttm_fence_object_flush(struct ttm_fence_object *fence, uint32_t flush_mask);
+
+/**
+ * ttm_fence_get_info
+ *
+ * @fence: The fence object.
+ *
+ * Copy the info block from the fence while holding relevant locks.
+ */
+
+struct ttm_fence_info ttm_fence_get_info(struct ttm_fence_object *fence);
+
+/**
+ * ttm_fence_object_ref
+ *
+ * @fence: The fence object.
+ *
+ * Return a ref-counted pointer to the fence object indicated by @fence.
+ */
+
+static inline struct ttm_fence_object *ttm_fence_object_ref(struct
+               ttm_fence_object
+               *fence) {
+       kref_get(&fence->kref);
+       return fence;
+}
+
+/**
+ * ttm_fence_object_unref
+ *
+ * @p_fence: Pointer to a ref-counted pinter to a struct ttm_fence_object.
+ *
+ * Unreference the fence object pointed to by *(@p_fence), clearing
+ * *(p_fence).
+ */
+
+extern void ttm_fence_object_unref(struct ttm_fence_object **p_fence);
+
+/**
+ * ttm_fence_object_signaled
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ * @mask: Type mask to check whether signaled.
+ *
+ * This function checks (without waiting) whether the fence object
+ * pointed to by @fence has signaled the types indicated by @mask,
+ * and returns 1 if true, 0 if false. This function does NOT perform
+ * an implicit fence flush.
+ */
+
+extern bool
+ttm_fence_object_signaled(struct ttm_fence_object *fence, uint32_t mask);
+
+/**
+ * ttm_fence_class
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ *
+ * Convenience function that returns the fence class of a
+ * struct ttm_fence_object.
+ */
+
+static inline uint32_t ttm_fence_class(const struct ttm_fence_object *fence)
+{
+       return fence->fence_class;
+}
+
+/**
+ * ttm_fence_types
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ *
+ * Convenience function that returns the fence types of a
+ * struct ttm_fence_object.
+ */
+
+static inline uint32_t ttm_fence_types(const struct ttm_fence_object *fence)
+{
+       return fence->fence_type;
+}
+
+/*
+ * The functions below are wrappers to the above functions, with
+ * similar names but with sync_obj omitted. These wrappers are intended
+ * to be plugged directly into the buffer object driver's sync object
+ * API, if the driver chooses to use ttm_fence_objects as buffer object
+ * sync objects. In the prototypes below, a sync_obj is cast to a
+ * struct ttm_fence_object, whereas a sync_arg is cast to an
+ * uint32_t representing a fence_type argument.
+ */
+
+extern bool ttm_fence_sync_obj_signaled(void *sync_obj, void *sync_arg);
+extern int ttm_fence_sync_obj_wait(void *sync_obj, void *sync_arg,
+                                  bool lazy, bool interruptible);
+extern int ttm_fence_sync_obj_flush(void *sync_obj, void *sync_arg);
+extern void ttm_fence_sync_obj_unref(void **sync_obj);
+extern void *ttm_fence_sync_obj_ref(void *sync_obj);
+
+#endif
diff --git a/drivers/staging/mrst/imgv/psb_ttm_fence_driver.h b/drivers/staging/mrst/imgv/psb_ttm_fence_driver.h
new file mode 100644 (file)
index 0000000..1402ecc
--- /dev/null
@@ -0,0 +1,299 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+#ifndef _TTM_FENCE_DRIVER_H_
+#define _TTM_FENCE_DRIVER_H_
+
+#include <linux/kref.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include "psb_ttm_fence_api.h"
+#include "ttm/ttm_memory.h"
+
+/** @file ttm_fence_driver.h
+ *
+ * Definitions needed for a driver implementing the
+ * ttm_fence subsystem.
+ */
+
+/**
+ * struct ttm_fence_class_manager:
+ *
+ * @wrap_diff: Sequence difference to catch 32-bit wrapping.
+ * if (seqa - seqb) > @wrap_diff, then seqa < seqb.
+ * @flush_diff: Sequence difference to trigger fence flush.
+ * if (cur_seq - seqa) > @flush_diff, then consider fence object with
+ * seqa as old an needing a flush.
+ * @sequence_mask: Mask of valid bits in a fence sequence.
+ * @lock: Lock protecting this struct as well as fence objects
+ * associated with this struct.
+ * @ring: Circular sequence-ordered list of fence objects.
+ * @pending_flush: Fence types currently needing a flush.
+ * @waiting_types: Fence types that are currently waited for.
+ * @fence_queue: Queue of waiters on fences belonging to this fence class.
+ * @highest_waiting_sequence: Sequence number of the fence with highest
+ * sequence number and that is waited for.
+ * @latest_queued_sequence: Sequence number of the fence latest queued
+ * on the ring.
+ */
+
+struct ttm_fence_class_manager {
+
+       /*
+        * Unprotected constant members.
+        */
+
+       uint32_t wrap_diff;
+       uint32_t flush_diff;
+       uint32_t sequence_mask;
+
+       /*
+        * The rwlock protects this structure as well as
+        * the data in all fence objects belonging to this
+        * class. This should be OK as most fence objects are
+        * only read from once they're created.
+        */
+
+       rwlock_t lock;
+       struct list_head ring;
+       uint32_t pending_flush;
+       uint32_t waiting_types;
+       wait_queue_head_t fence_queue;
+       uint32_t highest_waiting_sequence;
+       uint32_t latest_queued_sequence;
+};
+
+/**
+ * struct ttm_fence_device
+ *
+ * @fence_class:  Array of fence class managers.
+ * @num_classes:  Array dimension of @fence_class.
+ * @count:        Current number of fence objects for statistics.
+ * @driver:       Driver struct.
+ *
+ * Provided in the driver interface so that the driver can derive
+ * from this struct for its driver_private, and accordingly
+ * access the driver_private from the fence driver callbacks.
+ *
+ * All members except "count" are initialized at creation and
+ * never touched after that. No protection needed.
+ *
+ * This struct is private to the fence implementation and to the fence
+ * driver callbacks, and may otherwise be used by drivers only to
+ * obtain the derived device_private object using container_of().
+ */
+
+struct ttm_fence_device {
+       struct ttm_mem_global *mem_glob;
+       struct ttm_fence_class_manager *fence_class;
+       uint32_t num_classes;
+       atomic_t count;
+       const struct ttm_fence_driver *driver;
+};
+
+/**
+ * struct ttm_fence_class_init
+ *
+ * @wrap_diff:    Fence sequence number wrap indicator. If
+ * (sequence1 - sequence2) > @wrap_diff, then sequence1 is
+ * considered to be older than sequence2.
+ * @flush_diff:   Fence sequence number flush indicator.
+ * If a non-completely-signaled fence has a fence sequence number
+ * sequence1 and (sequence1 - current_emit_sequence) > @flush_diff,
+ * the fence is considered too old and it will be flushed upon the
+ * next call of ttm_fence_flush_old(), to make sure no fences with
+ * stale sequence numbers remains unsignaled. @flush_diff should
+ * be sufficiently less than @wrap_diff.
+ * @sequence_mask: Mask with valid bits of the fence sequence
+ * number set to 1.
+ *
+ * This struct is used as input to ttm_fence_device_init.
+ */
+
+struct ttm_fence_class_init {
+       uint32_t wrap_diff;
+       uint32_t flush_diff;
+       uint32_t sequence_mask;
+};
+
+/**
+ * struct ttm_fence_driver
+ *
+ * @has_irq: Called by a potential waiter. Should return 1 if a
+ * fence object with indicated parameters is expected to signal
+ * automatically, and 0 if the fence implementation needs to
+ * repeatedly call @poll to make it signal.
+ * @emit:    Make sure a fence with the given parameters is
+ * present in the indicated command stream. Return its sequence number
+ * in "breadcrumb".
+ * @poll:    Check and report sequences of the given "fence_class"
+ *           that have signaled "types"
+ * @flush:   Make sure that the types indicated by the bitfield
+ *           ttm_fence_class_manager::pending_flush will eventually
+ *           signal. These bits have been put together using the
+ *           result from the needed_flush function described below.
+ * @needed_flush: Given the fence_class and fence_types indicated by
+ *           "fence", and the last received fence sequence of this
+ *           fence class, indicate what types need a fence flush to
+ *           signal. Return as a bitfield.
+ * @wait:    Set to non-NULL if the driver wants to override the fence
+ *           wait implementation. Return 0 on success, -EBUSY on failure,
+ *           and -ERESTART if interruptible and a signal is pending.
+ * @signaled:  Driver callback that is called whenever a
+ *           ttm_fence_object::signaled_types has changed status.
+ *           This function is called from atomic context,
+ *           with the ttm_fence_class_manager::lock held in write mode.
+ * @lockup:  Driver callback that is called whenever a wait has exceeded
+ *           the lifetime of a fence object.
+ *           If there is a GPU lockup,
+ *           this function should, if possible, reset the GPU,
+ *           call the ttm_fence_handler with an error status, and
+ *           return. If no lockup was detected, simply extend the
+ *           fence timeout_jiffies and return. The driver might
+ *           want to protect the lockup check with a mutex and cache a
+ *           non-locked-up status for a while to avoid an excessive
+ *           amount of lockup checks from every waiting thread.
+ */
+
+struct ttm_fence_driver {
+       bool (*has_irq)(struct ttm_fence_device *fdev,
+                       uint32_t fence_class, uint32_t flags);
+       int (*emit)(struct ttm_fence_device *fdev,
+                   uint32_t fence_class,
+                   uint32_t flags,
+                   uint32_t *breadcrumb, unsigned long *timeout_jiffies);
+       void (*flush)(struct ttm_fence_device *fdev, uint32_t fence_class);
+       void (*poll)(struct ttm_fence_device *fdev,
+                    uint32_t fence_class, uint32_t types);
+       uint32_t(*needed_flush)
+       (struct ttm_fence_object *fence);
+       int (*wait)(struct ttm_fence_object *fence, bool lazy,
+                   bool interruptible, uint32_t mask);
+       void (*signaled)(struct ttm_fence_object *fence);
+       void (*lockup)(struct ttm_fence_object *fence, uint32_t fence_types);
+};
+
+/**
+ * function ttm_fence_device_init
+ *
+ * @num_classes:      Number of fence classes for this fence implementation.
+ * @mem_global:       Pointer to the global memory accounting info.
+ * @fdev:             Pointer to an uninitialised struct ttm_fence_device.
+ * @init:             Array of initialization info for each fence class.
+ * @replicate_init:   Use the first @init initialization info for all classes.
+ * @driver:           Driver callbacks.
+ *
+ * Initialize a struct ttm_fence_driver structure. Returns -ENOMEM if
+ * out-of-memory. Otherwise returns 0.
+ */
+extern int
+ttm_fence_device_init(int num_classes,
+                     struct ttm_mem_global *mem_glob,
+                     struct ttm_fence_device *fdev,
+                     const struct ttm_fence_class_init *init,
+                     bool replicate_init,
+                     const struct ttm_fence_driver *driver);
+
+/**
+ * function ttm_fence_device_release
+ *
+ * @fdev:             Pointer to the fence device.
+ *
+ * Release all resources held by a fence device. Note that before
+ * this function is called, the caller must have made sure all fence
+ * objects belonging to this fence device are completely signaled.
+ */
+
+extern void ttm_fence_device_release(struct ttm_fence_device *fdev);
+
+/**
+ * ttm_fence_handler - the fence handler.
+ *
+ * @fdev:        Pointer to the fence device.
+ * @fence_class: Fence class that signals.
+ * @sequence:    Signaled sequence.
+ * @type:        Types that signal.
+ * @error:       Error from the engine.
+ *
+ * This function signals all fences with a sequence previous to the
+ * @sequence argument, and belonging to @fence_class. The signaled fence
+ * types are provided in @type. If error is non-zero, the error member
+ * of the fence with sequence = @sequence is set to @error. This value
+ * may be reported back to user-space, indicating, for example an illegal
+ * 3D command or illegal mpeg data.
+ *
+ * This function is typically called from the driver::poll method when the
+ * command sequence preceding the fence marker has executed. It should be
+ * called with the ttm_fence_class_manager::lock held in write mode and
+ * may be called from interrupt context.
+ */
+
+extern void
+ttm_fence_handler(struct ttm_fence_device *fdev,
+                 uint32_t fence_class,
+                 uint32_t sequence, uint32_t type, uint32_t error);
+
+/**
+ * ttm_fence_driver_from_dev
+ *
+ * @fdev:        The ttm fence device.
+ *
+ * Returns a pointer to the fence driver struct.
+ */
+
+static inline const struct ttm_fence_driver *ttm_fence_driver_from_dev(
+       struct ttm_fence_device *fdev) {
+       return fdev->driver;
+}
+
+/**
+ * ttm_fence_driver
+ *
+ * @fence:        Pointer to a ttm fence object.
+ *
+ * Returns a pointer to the fence driver struct.
+ */
+
+static inline const struct ttm_fence_driver *ttm_fence_driver(struct
+               ttm_fence_object
+               *fence) {
+       return ttm_fence_driver_from_dev(fence->fdev);
+}
+
+/**
+ * ttm_fence_fc
+ *
+ * @fence:        Pointer to a ttm fence object.
+ *
+ * Returns a pointer to the struct ttm_fence_class_manager for the
+ * fence class of @fence.
+ */
+
+static inline struct ttm_fence_class_manager *ttm_fence_fc(struct
+               ttm_fence_object
+               *fence) {
+       return &fence->fdev->fence_class[fence->fence_class];
+}
+
+#endif
diff --git a/drivers/staging/mrst/imgv/psb_ttm_fence_user.c b/drivers/staging/mrst/imgv/psb_ttm_fence_user.c
new file mode 100644 (file)
index 0000000..c333788
--- /dev/null
@@ -0,0 +1,236 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_ttm_fence_user.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_driver.h"
+#include "psb_ttm_userobj_api.h"
+
+/**
+ * struct ttm_fence_user_object
+ *
+ * @base:    The base object used for user-space visibility and refcounting.
+ *
+ * @fence:   The fence object itself.
+ *
+ */
+
+struct ttm_fence_user_object {
+       struct ttm_base_object base;
+       struct ttm_fence_object fence;
+};
+
+static struct ttm_fence_user_object *ttm_fence_user_object_lookup(
+       struct ttm_object_file *tfile,
+       uint32_t handle) {
+       struct ttm_base_object *base;
+
+       base = ttm_base_object_lookup(tfile, handle);
+       if (unlikely(base == NULL)) {
+               printk(KERN_ERR "Invalid fence handle 0x%08lx\n",
+                      (unsigned long)handle);
+               return NULL;
+       }
+
+       if (unlikely(base->object_type != ttm_fence_type)) {
+               ttm_base_object_unref(&base);
+               printk(KERN_ERR "Invalid fence handle 0x%08lx\n",
+                      (unsigned long)handle);
+               return NULL;
+       }
+
+       return container_of(base, struct ttm_fence_user_object, base);
+}
+
+/*
+ * The fence object destructor.
+ */
+
+static void ttm_fence_user_destroy(struct ttm_fence_object *fence)
+{
+       struct ttm_fence_user_object *ufence =
+               container_of(fence, struct ttm_fence_user_object, fence);
+
+       ttm_mem_global_free(fence->fdev->mem_glob, sizeof(*ufence));
+       kfree(ufence);
+}
+
+/*
+ * The base object destructor. We basically unly unreference the
+ * attached fence object.
+ */
+
+static void ttm_fence_user_release(struct ttm_base_object **p_base)
+{
+       struct ttm_fence_user_object *ufence;
+       struct ttm_base_object *base = *p_base;
+       struct ttm_fence_object *fence;
+
+       *p_base = NULL;
+
+       if (unlikely(base == NULL))
+               return;
+
+       ufence = container_of(base, struct ttm_fence_user_object, base);
+       fence = &ufence->fence;
+       ttm_fence_object_unref(&fence);
+}
+
+int
+ttm_fence_user_create(struct ttm_fence_device *fdev,
+                     struct ttm_object_file *tfile,
+                     uint32_t fence_class,
+                     uint32_t fence_types,
+                     uint32_t create_flags,
+                     struct ttm_fence_object **fence,
+                     uint32_t *user_handle)
+{
+       int ret;
+       struct ttm_fence_object *tmp;
+       struct ttm_fence_user_object *ufence;
+
+       ret = ttm_mem_global_alloc(fdev->mem_glob,
+                                  sizeof(*ufence),
+                                  false,
+                                  false);
+       if (unlikely(ret != 0))
+               return -ENOMEM;
+
+       ufence = kmalloc(sizeof(*ufence), GFP_KERNEL);
+       if (unlikely(ufence == NULL)) {
+               ttm_mem_global_free(fdev->mem_glob, sizeof(*ufence));
+               return -ENOMEM;
+       }
+
+       ret = ttm_fence_object_init(fdev,
+                                   fence_class,
+                                   fence_types, create_flags,
+                                   &ttm_fence_user_destroy, &ufence->fence);
+
+       if (unlikely(ret != 0))
+               goto out_err0;
+
+       /*
+        * One fence ref is held by the fence ptr we return.
+        * The other one by the base object. Need to up the
+        * fence refcount before we publish this object to
+        * user-space.
+        */
+
+       tmp = ttm_fence_object_ref(&ufence->fence);
+       ret = ttm_base_object_init(tfile, &ufence->base,
+                                  false, ttm_fence_type,
+                                  &ttm_fence_user_release, NULL);
+
+       if (unlikely(ret != 0))
+               goto out_err1;
+
+       *fence = &ufence->fence;
+       *user_handle = ufence->base.hash.key;
+
+       return 0;
+out_err1:
+       ttm_fence_object_unref(&tmp);
+       tmp = &ufence->fence;
+       ttm_fence_object_unref(&tmp);
+       return ret;
+out_err0:
+       ttm_mem_global_free(fdev->mem_glob, sizeof(*ufence));
+       kfree(ufence);
+       return ret;
+}
+
+int ttm_fence_signaled_ioctl(struct ttm_object_file *tfile, void *data)
+{
+       int ret;
+       union ttm_fence_signaled_arg *arg = data;
+       struct ttm_fence_object *fence;
+       struct ttm_fence_info info;
+       struct ttm_fence_user_object *ufence;
+       struct ttm_base_object *base;
+       ret = 0;
+
+       ufence = ttm_fence_user_object_lookup(tfile, arg->req.handle);
+       if (unlikely(ufence == NULL))
+               return -EINVAL;
+
+       fence = &ufence->fence;
+
+       if (arg->req.flush) {
+               ret = ttm_fence_object_flush(fence, arg->req.fence_type);
+               if (unlikely(ret != 0))
+                       goto out;
+       }
+
+       info = ttm_fence_get_info(fence);
+       arg->rep.signaled_types = info.signaled_types;
+       arg->rep.fence_error = info.error;
+
+out:
+       base = &ufence->base;
+       ttm_base_object_unref(&base);
+       return ret;
+}
+
+int ttm_fence_finish_ioctl(struct ttm_object_file *tfile, void *data)
+{
+       int ret;
+       union ttm_fence_finish_arg *arg = data;
+       struct ttm_fence_user_object *ufence;
+       struct ttm_base_object *base;
+       struct ttm_fence_object *fence;
+       ret = 0;
+
+       ufence = ttm_fence_user_object_lookup(tfile, arg->req.handle);
+       if (unlikely(ufence == NULL))
+               return -EINVAL;
+
+       fence = &ufence->fence;
+
+       ret = ttm_fence_object_wait(fence,
+                                   arg->req.mode & TTM_FENCE_FINISH_MODE_LAZY,
+                                   true, arg->req.fence_type);
+       if (likely(ret == 0)) {
+               struct ttm_fence_info info = ttm_fence_get_info(fence);
+
+               arg->rep.signaled_types = info.signaled_types;
+               arg->rep.fence_error = info.error;
+       }
+
+       base = &ufence->base;
+       ttm_base_object_unref(&base);
+
+       return ret;
+}
+
+int ttm_fence_unref_ioctl(struct ttm_object_file *tfile, void *data)
+{
+       struct ttm_fence_unref_arg *arg = data;
+       int ret = 0;
+
+       ret = ttm_ref_object_base_unref(tfile, arg->handle, ttm_fence_type);
+       return ret;
+}
diff --git a/drivers/staging/mrst/imgv/psb_ttm_fence_user.h b/drivers/staging/mrst/imgv/psb_ttm_fence_user.h
new file mode 100644 (file)
index 0000000..fc13f89
--- /dev/null
@@ -0,0 +1,140 @@
+/**************************************************************************
+ *
+ * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef TTM_FENCE_USER_H
+#define TTM_FENCE_USER_H
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#endif
+
+#define TTM_FENCE_MAJOR 0
+#define TTM_FENCE_MINOR 1
+#define TTM_FENCE_PL    0
+#define TTM_FENCE_DATE  "080819"
+
+/**
+ * struct ttm_fence_signaled_req
+ *
+ * @handle: Handle to the fence object. Input.
+ *
+ * @fence_type: Fence types we want to flush. Input.
+ *
+ * @flush: Boolean. Flush the indicated fence_types. Input.
+ *
+ * Argument to the TTM_FENCE_SIGNALED ioctl.
+ */
+
+struct ttm_fence_signaled_req {
+       uint32_t handle;
+       uint32_t fence_type;
+       int32_t flush;
+       uint32_t pad64;
+};
+
+/**
+ * struct ttm_fence_rep
+ *
+ * @signaled_types: Fence type that has signaled.
+ *
+ * @fence_error: Command execution error.
+ * Hardware errors that are consequences of the execution
+ * of the command stream preceding the fence are reported
+ * here.
+ *
+ * Output argument to the TTM_FENCE_SIGNALED and
+ * TTM_FENCE_FINISH ioctls.
+ */
+
+struct ttm_fence_rep {
+       uint32_t signaled_types;
+       uint32_t fence_error;
+};
+
+union ttm_fence_signaled_arg {
+       struct ttm_fence_signaled_req req;
+       struct ttm_fence_rep rep;
+};
+
+/*
+ * Waiting mode flags for the TTM_FENCE_FINISH ioctl.
+ *
+ * TTM_FENCE_FINISH_MODE_LAZY: Allow for sleeps during polling
+ * wait.
+ *
+ * TTM_FENCE_FINISH_MODE_NO_BLOCK: Don't block waiting for GPU,
+ * but return -EBUSY if the buffer is busy.
+ */
+
+#define TTM_FENCE_FINISH_MODE_LAZY     (1 << 0)
+#define TTM_FENCE_FINISH_MODE_NO_BLOCK (1 << 1)
+
+/**
+ * struct ttm_fence_finish_req
+ *
+ * @handle: Handle to the fence object. Input.
+ *
+ * @fence_type: Fence types we want to finish.
+ *
+ * @mode: Wait mode.
+ *
+ * Input to the TTM_FENCE_FINISH ioctl.
+ */
+
+struct ttm_fence_finish_req {
+       uint32_t handle;
+       uint32_t fence_type;
+       uint32_t mode;
+       uint32_t pad64;
+};
+
+union ttm_fence_finish_arg {
+       struct ttm_fence_finish_req req;
+       struct ttm_fence_rep rep;
+};
+
+/**
+ * struct ttm_fence_unref_arg
+ *
+ * @handle: Handle to the fence object.
+ *
+ * Argument to the TTM_FENCE_UNREF ioctl.
+ */
+
+struct ttm_fence_unref_arg {
+       uint32_t handle;
+       uint32_t pad64;
+};
+
+/*
+ * Ioctl offsets frome extenstion start.
+ */
+
+#define TTM_FENCE_SIGNALED 0x01
+#define TTM_FENCE_FINISH   0x02
+#define TTM_FENCE_UNREF    0x03
+
+#endif
diff --git a/drivers/staging/mrst/imgv/psb_ttm_glue.c b/drivers/staging/mrst/imgv/psb_ttm_glue.c
new file mode 100644 (file)
index 0000000..d2010eb
--- /dev/null
@@ -0,0 +1,377 @@
+/**************************************************************************
+ * Copyright (c) 2008, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_ttm_userobj_api.h"
+#include <linux/io.h>
+#include "psb_msvdx.h"
+#include "bufferclass_video.h"
+#include "bufferclass_video_linux.h"
+
+/*IMG Headers*/
+#include "private_data.h"
+
+extern int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma);
+int BC_DestroyBuffers(int id);
+
+static struct vm_operations_struct psb_ttm_vm_ops;
+
+/**
+ * NOTE: driver_private of drm_file is now a PVRSRV_FILE_PRIVATE_DATA struct
+ * pPriv in PVRSRV_FILE_PRIVATE_DATA contains the original psb_fpriv;
+ */
+int psb_open(struct inode *inode, struct file *filp)
+{
+       struct drm_file *file_priv;
+       struct drm_psb_private *dev_priv;
+       struct psb_fpriv *psb_fp;
+       PVRSRV_FILE_PRIVATE_DATA *pvr_file_priv;
+       int ret;
+
+       DRM_DEBUG("\n");
+
+       ret = drm_open(inode, filp);
+       if (unlikely(ret))
+               return ret;
+
+       psb_fp = kzalloc(sizeof(*psb_fp), GFP_KERNEL);
+
+       if (unlikely(psb_fp == NULL))
+               goto out_err0;
+
+       file_priv = (struct drm_file *) filp->private_data;
+       dev_priv = psb_priv(file_priv->minor->dev);
+
+       DRM_DEBUG("is_master %d\n", file_priv->is_master ? 1 : 0);
+
+       psb_fp->tfile = ttm_object_file_init(dev_priv->tdev,
+                                            PSB_FILE_OBJECT_HASH_ORDER);
+       if (unlikely(psb_fp->tfile == NULL))
+               goto out_err1;
+
+       pvr_file_priv = (PVRSRV_FILE_PRIVATE_DATA *)file_priv->driver_priv;
+       if (!pvr_file_priv) {
+               DRM_ERROR("drm file private is NULL\n");
+               goto out_err1;
+       }
+
+       pvr_file_priv->pPriv = psb_fp;
+       if (unlikely(dev_priv->bdev.dev_mapping == NULL))
+               dev_priv->bdev.dev_mapping = dev_priv->dev->dev_mapping;
+
+       return 0;
+
+out_err1:
+       kfree(psb_fp);
+out_err0:
+       (void) drm_release(inode, filp);
+       return ret;
+}
+
+int psb_release(struct inode *inode, struct file *filp)
+{
+       struct drm_file *file_priv;
+       struct psb_fpriv *psb_fp;
+       struct drm_psb_private *dev_priv;
+       struct msvdx_private *msvdx_priv;
+       int ret;
+       file_priv = (struct drm_file *) filp->private_data;
+       psb_fp = psb_fpriv(file_priv);
+       dev_priv = psb_priv(file_priv->minor->dev);
+       msvdx_priv = (struct msvdx_private *)dev_priv->msvdx_private;
+
+       /*cleanup for msvdx*/
+       if (msvdx_priv->tfile == psb_fpriv(file_priv)->tfile) {
+               msvdx_priv->fw_status = 0;
+               msvdx_priv->host_be_opp_enabled = 0;
+               msvdx_priv->deblock_enabled = 0;
+               memset(&msvdx_priv->frame_info, 0, sizeof(struct drm_psb_msvdx_frame_info) * MAX_DECODE_BUFFERS);
+       }
+
+       if (psb_fp->bcd_index >= 0 &&
+           psb_fp->bcd_index < BC_VIDEO_DEVICE_MAX_ID &&
+           bc_video_id_usage[psb_fp->bcd_index] == 1) {
+               bc_video_id_usage[psb_fp->bcd_index] = 0;
+               BC_DestroyBuffers(psb_fp->bcd_index);
+       }
+
+       ttm_object_file_release(&psb_fp->tfile);
+       kfree(psb_fp);
+
+       /* remove video context */
+       psb_remove_videoctx(dev_priv, filp);
+
+       ret = drm_release(inode, filp);
+
+       return ret;
+}
+
+int psb_fence_signaled_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv)
+{
+
+       return ttm_fence_signaled_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_fence_finish_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       return ttm_fence_finish_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_fence_unref_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       return ttm_fence_unref_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_waitidle_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       return ttm_pl_waitidle_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_setstatus_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       return ttm_pl_setstatus_ioctl(psb_fpriv(file_priv)->tfile,
+                                     &psb_priv(dev)->ttm_lock, data);
+
+}
+
+int psb_pl_synccpu_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       return ttm_pl_synccpu_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_unref_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       return ttm_pl_unref_ioctl(psb_fpriv(file_priv)->tfile, data);
+
+}
+
+int psb_pl_reference_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       return  ttm_pl_reference_ioctl(psb_fpriv(file_priv)->tfile, data);
+
+}
+
+int psb_pl_create_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+
+       return ttm_pl_create_ioctl(psb_fpriv(file_priv)->tfile,
+                                  &dev_priv->bdev, &dev_priv->ttm_lock, data);
+
+}
+
+int psb_pl_ub_create_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+
+       return ttm_pl_ub_create_ioctl(psb_fpriv(file_priv)->tfile,
+                                     &dev_priv->bdev, &dev_priv->ttm_lock, data);
+
+}
+/**
+ * psb_ttm_fault - Wrapper around the ttm fault method.
+ *
+ * @vma: The struct vm_area_struct as in the vm fault() method.
+ * @vmf: The struct vm_fault as in the vm fault() method.
+ *
+ * Since ttm_fault() will reserve buffers while faulting,
+ * we need to take the ttm read lock around it, as this driver
+ * relies on the ttm_lock in write mode to exclude all threads from
+ * reserving and thus validating buffers in aperture- and memory shortage
+ * situations.
+ */
+
+static int psb_ttm_fault(struct vm_area_struct *vma,
+                        struct vm_fault *vmf)
+{
+       struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
+                                      vma->vm_private_data;
+       struct drm_psb_private *dev_priv =
+               container_of(bo->bdev, struct drm_psb_private, bdev);
+       int ret;
+
+       ret = ttm_read_lock(&dev_priv->ttm_lock, true);
+       if (unlikely(ret != 0))
+               return VM_FAULT_NOPAGE;
+
+       ret = dev_priv->ttm_vm_ops->fault(vma, vmf);
+
+       ttm_read_unlock(&dev_priv->ttm_lock);
+       return ret;
+}
+
+/**
+ * if vm_pgoff < DRM_PSB_FILE_PAGE_OFFSET call directly to
+ * PVRMMap
+ */
+int psb_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *file_priv;
+       struct drm_psb_private *dev_priv;
+       int ret;
+
+       if (vma->vm_pgoff < DRM_PSB_FILE_PAGE_OFFSET ||
+           vma->vm_pgoff > 2 * DRM_PSB_FILE_PAGE_OFFSET)
+               return PVRMMap(filp, vma);
+
+       file_priv = (struct drm_file *) filp->private_data;
+       dev_priv = psb_priv(file_priv->minor->dev);
+
+       ret = ttm_bo_mmap(filp, vma, &dev_priv->bdev);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (unlikely(dev_priv->ttm_vm_ops == NULL)) {
+               dev_priv->ttm_vm_ops = (struct vm_operations_struct *)vma->vm_ops;
+               psb_ttm_vm_ops = *vma->vm_ops;
+               psb_ttm_vm_ops.fault = &psb_ttm_fault;
+       }
+
+       vma->vm_ops = &psb_ttm_vm_ops;
+
+       return 0;
+}
+/*
+ssize_t psb_ttm_write(struct file *filp, const char __user *buf,
+                     size_t count, loff_t *f_pos)
+{
+       struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+       struct drm_psb_private *dev_priv = psb_priv(file_priv->minor->dev);
+
+       return ttm_bo_io(&dev_priv->bdev, filp, buf, NULL, count, f_pos, 1);
+}
+
+ssize_t psb_ttm_read(struct file *filp, char __user *buf,
+                    size_t count, loff_t *f_pos)
+{
+       struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+       struct drm_psb_private *dev_priv = psb_priv(file_priv->minor->dev);
+
+       return ttm_bo_io(&dev_priv->bdev, filp, NULL, buf, count, f_pos, 1);
+}
+*/
+int psb_verify_access(struct ttm_buffer_object *bo,
+                     struct file *filp)
+{
+       struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+
+       if (capable(CAP_SYS_ADMIN))
+               return 0;
+
+       if (unlikely(!file_priv->authenticated))
+               return -EPERM;
+
+       return ttm_pl_verify_access(bo, psb_fpriv(file_priv)->tfile);
+}
+
+static int psb_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+       return ttm_mem_global_init(ref->object);
+}
+
+static void psb_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+       ttm_mem_global_release(ref->object);
+}
+
+int psb_ttm_global_init(struct drm_psb_private *dev_priv)
+{
+       struct drm_global_reference *global_ref;
+       struct drm_global_reference *global;
+       int ret;
+
+       global_ref = &dev_priv->mem_global_ref;
+       global_ref->global_type = DRM_GLOBAL_TTM_MEM;
+       global_ref->size = sizeof(struct ttm_mem_global);
+       global_ref->init = &psb_ttm_mem_global_init;
+       global_ref->release = &psb_ttm_mem_global_release;
+
+       ret = drm_global_item_ref(global_ref);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed referencing a global TTM memory object.\n");
+               return ret;
+       }
+
+       dev_priv->bo_global_ref.mem_glob = dev_priv->mem_global_ref.object;
+       global = &dev_priv->bo_global_ref.ref;
+       global->global_type = DRM_GLOBAL_TTM_BO;
+       global->size = sizeof(struct ttm_bo_global);
+       global->init = &ttm_bo_global_init;
+       global->release = &ttm_bo_global_release;
+       ret = drm_global_item_ref(global);
+       if (ret != 0) {
+               DRM_ERROR("Failed setting up TTM BO subsystem.\n");
+               drm_global_item_unref(global_ref);
+               return ret;
+       }
+
+       return 0;
+}
+
+void psb_ttm_global_release(struct drm_psb_private *dev_priv)
+{
+       drm_global_item_unref(&dev_priv->mem_global_ref);
+}
+
+int psb_getpageaddrs_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_psb_getpageaddrs_arg *arg = data;
+       struct ttm_buffer_object *bo;
+       struct ttm_tt *ttm;
+       struct page **tt_pages;
+       unsigned long i, num_pages;
+       unsigned long *p = arg->page_addrs;
+       int ret = 0;
+
+       bo = ttm_buffer_object_lookup(psb_fpriv(file_priv)->tfile,
+                                     arg->handle);
+       if (unlikely(bo == NULL)) {
+               printk(KERN_ERR
+                      "Could not find buffer object for getpageaddrs.\n");
+               return -EINVAL;
+       }
+
+       arg->gtt_offset = bo->offset;
+       ttm = bo->ttm;
+       num_pages = ttm->num_pages;
+       tt_pages = ttm->pages;
+
+       for (i = 0; i < num_pages; i++)
+               p[i] = (unsigned long)page_to_phys(tt_pages[i]);
+
+       if (bo)
+               ttm_bo_unref(&bo);
+
+       return ret;
+}
diff --git a/drivers/staging/mrst/imgv/psb_ttm_placement_user.c b/drivers/staging/mrst/imgv/psb_ttm_placement_user.c
new file mode 100644 (file)
index 0000000..3ef4870
--- /dev/null
@@ -0,0 +1,632 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "psb_ttm_placement_user.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_lock.h"
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+struct ttm_bo_user_object {
+       struct ttm_base_object base;
+       struct ttm_buffer_object bo;
+};
+
+static size_t pl_bo_size;
+
+static uint32_t psb_busy_prios[] = {
+       TTM_PL_TT,
+       TTM_PL_PRIV0, /* CI */
+       TTM_PL_PRIV2, /* RAR */
+       TTM_PL_PRIV1, /* DRM_PSB_MEM_MMU */
+       TTM_PL_SYSTEM
+};
+
+static const struct ttm_placement default_placement = {0, 0, 0, NULL, 5, psb_busy_prios};
+
+static size_t ttm_pl_size(struct ttm_bo_device *bdev, unsigned long num_pages)
+{
+       size_t page_array_size =
+               (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK;
+
+       if (unlikely(pl_bo_size == 0)) {
+               pl_bo_size = bdev->glob->ttm_bo_extra_size +
+                            ttm_round_pot(sizeof(struct ttm_bo_user_object));
+       }
+
+       return bdev->glob->ttm_bo_size + 2 * page_array_size;
+}
+
+static struct ttm_bo_user_object *ttm_bo_user_lookup(struct ttm_object_file
+               *tfile, uint32_t handle) {
+       struct ttm_base_object *base;
+
+       base = ttm_base_object_lookup(tfile, handle);
+       if (unlikely(base == NULL)) {
+               printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+                      (unsigned long)handle);
+               return NULL;
+       }
+
+       if (unlikely(base->object_type != ttm_buffer_type)) {
+               ttm_base_object_unref(&base);
+               printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+                      (unsigned long)handle);
+               return NULL;
+       }
+
+       return container_of(base, struct ttm_bo_user_object, base);
+}
+
+struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file
+               *tfile, uint32_t handle) {
+       struct ttm_bo_user_object *user_bo;
+       struct ttm_base_object *base;
+
+       user_bo = ttm_bo_user_lookup(tfile, handle);
+       if (unlikely(user_bo == NULL))
+               return NULL;
+
+       (void)ttm_bo_reference(&user_bo->bo);
+       base = &user_bo->base;
+       ttm_base_object_unref(&base);
+       return &user_bo->bo;
+}
+
+static void ttm_bo_user_destroy(struct ttm_buffer_object *bo)
+{
+       struct ttm_bo_user_object *user_bo =
+               container_of(bo, struct ttm_bo_user_object, bo);
+
+       ttm_mem_global_free(bo->glob->mem_glob, bo->acc_size);
+       kfree(user_bo);
+}
+
+static void ttm_bo_user_release(struct ttm_base_object **p_base)
+{
+       struct ttm_bo_user_object *user_bo;
+       struct ttm_base_object *base = *p_base;
+       struct ttm_buffer_object *bo;
+
+       *p_base = NULL;
+
+       if (unlikely(base == NULL))
+               return;
+
+       user_bo = container_of(base, struct ttm_bo_user_object, base);
+       bo = &user_bo->bo;
+       ttm_bo_unref(&bo);
+}
+
+static void ttm_bo_user_ref_release(struct ttm_base_object *base,
+                                   enum ttm_ref_type ref_type)
+{
+       struct ttm_bo_user_object *user_bo =
+               container_of(base, struct ttm_bo_user_object, base);
+       struct ttm_buffer_object *bo = &user_bo->bo;
+
+       switch (ref_type) {
+       case TTM_REF_SYNCCPU_WRITE:
+               ttm_bo_synccpu_write_release(bo);
+               break;
+       default:
+               BUG();
+       }
+}
+
+static void ttm_pl_fill_rep(struct ttm_buffer_object *bo,
+                           struct ttm_pl_rep *rep)
+{
+       struct ttm_bo_user_object *user_bo =
+               container_of(bo, struct ttm_bo_user_object, bo);
+
+       rep->gpu_offset = bo->offset;
+       rep->bo_size = bo->num_pages << PAGE_SHIFT;
+       rep->map_handle = bo->addr_space_offset;
+       rep->placement = bo->mem.placement;
+       rep->handle = user_bo->base.hash.key;
+       rep->sync_object_arg = (uint32_t)(unsigned long)bo->sync_obj_arg;
+}
+
+/* FIXME Copy from upstream TTM */
+static inline size_t ttm_bo_size(struct ttm_bo_global *glob,
+                                unsigned long num_pages)
+{
+       size_t page_array_size = (num_pages * sizeof(void *) + PAGE_SIZE - 1) &
+                                PAGE_MASK;
+
+       return glob->ttm_bo_size + 2 * page_array_size;
+}
+
+/* FIXME Copy from upstream TTM "ttm_bo_create", upstream TTM does not export this, so copy it here */
+static int ttm_bo_create_private(struct ttm_bo_device *bdev,
+                                unsigned long size,
+                                enum ttm_bo_type type,
+                                struct ttm_placement *placement,
+                                uint32_t page_alignment,
+                                unsigned long buffer_start,
+                                bool interruptible,
+                                struct file *persistant_swap_storage,
+                                struct ttm_buffer_object **p_bo)
+{
+       struct ttm_buffer_object *bo;
+       struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+       int ret;
+
+       size_t acc_size =
+               ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+       ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+       if (unlikely(ret != 0))
+               return ret;
+
+       bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+
+       if (unlikely(bo == NULL)) {
+               ttm_mem_global_free(mem_glob, acc_size);
+               return -ENOMEM;
+       }
+
+       ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
+                         buffer_start, interruptible,
+                         persistant_swap_storage, acc_size, NULL);
+       if (likely(ret == 0))
+               *p_bo = bo;
+
+       return ret;
+}
+
+int psb_ttm_bo_check_placement(struct ttm_buffer_object *bo,
+                              struct ttm_placement *placement)
+{
+       int i;
+
+       for (i = 0; i < placement->num_placement; i++) {
+               if (!capable(CAP_SYS_ADMIN)) {
+                       if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) {
+                               printk(KERN_ERR TTM_PFX "Need to be root to "
+                                      "modify NO_EVICT status.\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+       for (i = 0; i < placement->num_busy_placement; i++) {
+               if (!capable(CAP_SYS_ADMIN)) {
+                       if (placement->busy_placement[i] & TTM_PL_FLAG_NO_EVICT) {
+                               printk(KERN_ERR TTM_PFX "Need to be root to "
+                                      "modify NO_EVICT status.\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+       return 0;
+}
+
+int ttm_buffer_object_create(struct ttm_bo_device *bdev,
+                            unsigned long size,
+                            enum ttm_bo_type type,
+                            uint32_t flags,
+                            uint32_t page_alignment,
+                            unsigned long buffer_start,
+                            bool interruptible,
+                            struct file *persistant_swap_storage,
+                            struct ttm_buffer_object **p_bo)
+{
+       struct ttm_placement placement = default_placement;
+       int ret;
+
+       if ((flags & TTM_PL_MASK_CACHING) == 0)
+               flags |= TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+
+       placement.num_placement = 1;
+       placement.placement = &flags;
+
+       ret = ttm_bo_create_private(bdev,
+                                   size,
+                                   type,
+                                   &placement,
+                                   page_alignment,
+                                   buffer_start,
+                                   interruptible,
+                                   persistant_swap_storage,
+                                   p_bo);
+
+       return ret;
+}
+
+
+int ttm_pl_create_ioctl(struct ttm_object_file *tfile,
+                       struct ttm_bo_device *bdev,
+                       struct ttm_lock *lock, void *data)
+{
+       union ttm_pl_create_arg *arg = data;
+       struct ttm_pl_create_req *req = &arg->req;
+       struct ttm_pl_rep *rep = &arg->rep;
+       struct ttm_buffer_object *bo;
+       struct ttm_buffer_object *tmp;
+       struct ttm_bo_user_object *user_bo;
+       uint32_t flags;
+       int ret = 0;
+       struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+       struct ttm_placement placement = default_placement;
+       size_t acc_size =
+               ttm_pl_size(bdev, (req->size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+       ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+       if (unlikely(ret != 0))
+               return ret;
+
+       flags = req->placement;
+       user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL);
+       if (unlikely(user_bo == NULL)) {
+               ttm_mem_global_free(mem_glob, acc_size);
+               return -ENOMEM;
+       }
+
+       bo = &user_bo->bo;
+       ret = ttm_read_lock(lock, true);
+       if (unlikely(ret != 0)) {
+               ttm_mem_global_free(mem_glob, acc_size);
+               kfree(user_bo);
+               return ret;
+       }
+
+       placement.num_placement = 1;
+       placement.placement = &flags;
+
+       if ((flags & TTM_PL_MASK_CACHING) == 0)
+               flags |=  TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+
+       ret = ttm_bo_init(bdev, bo, req->size,
+                         ttm_bo_type_device, &placement,
+                         req->page_alignment, 0, true,
+                         NULL, acc_size, &ttm_bo_user_destroy);
+       ttm_read_unlock(lock);
+
+       /*
+        * Note that the ttm_buffer_object_init function
+        * would've called the destroy function on failure!!
+        */
+
+       if (unlikely(ret != 0))
+               goto out;
+
+       tmp = ttm_bo_reference(bo);
+       ret = ttm_base_object_init(tfile, &user_bo->base,
+                                  flags & TTM_PL_FLAG_SHARED,
+                                  ttm_buffer_type,
+                                  &ttm_bo_user_release,
+                                  &ttm_bo_user_ref_release);
+       if (unlikely(ret != 0))
+               goto out_err;
+
+       spin_lock(&bo->bdev->fence_lock);
+       ttm_pl_fill_rep(bo, rep);
+       spin_unlock(&bo->bdev->fence_lock);
+       ttm_bo_unref(&bo);
+out:
+       return 0;
+out_err:
+       ttm_bo_unref(&tmp);
+       ttm_bo_unref(&bo);
+       return ret;
+}
+
+int ttm_pl_ub_create_ioctl(struct ttm_object_file *tfile,
+                          struct ttm_bo_device *bdev,
+                          struct ttm_lock *lock, void *data)
+{
+       union ttm_pl_create_ub_arg *arg = data;
+       struct ttm_pl_create_ub_req *req = &arg->req;
+       struct ttm_pl_rep *rep = &arg->rep;
+       struct ttm_buffer_object *bo;
+       struct ttm_buffer_object *tmp;
+       struct ttm_bo_user_object *user_bo;
+       uint32_t flags;
+       int ret = 0;
+       struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+       struct ttm_placement placement = default_placement;
+       size_t acc_size =
+               ttm_pl_size(bdev, (req->size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+       ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+       if (unlikely(ret != 0))
+               return ret;
+
+       flags = req->placement;
+       user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL);
+       if (unlikely(user_bo == NULL)) {
+               ttm_mem_global_free(mem_glob, acc_size);
+               return -ENOMEM;
+       }
+       ret = ttm_read_lock(lock, true);
+       if (unlikely(ret != 0)) {
+               ttm_mem_global_free(mem_glob, acc_size);
+               kfree(user_bo);
+               return ret;
+       }
+       bo = &user_bo->bo;
+
+       placement.num_placement = 1;
+       placement.placement = &flags;
+
+       ret = ttm_bo_init(bdev,
+                         bo,
+                         req->size,
+                         ttm_bo_type_user,
+                         &placement,
+                         req->page_alignment,
+                         req->user_address,
+                         true,
+                         NULL,
+                         acc_size,
+                         &ttm_bo_user_destroy);
+
+       /*
+        * Note that the ttm_buffer_object_init function
+        * would've called the destroy function on failure!!
+        */
+       ttm_read_unlock(lock);
+       if (unlikely(ret != 0))
+               goto out;
+
+       tmp = ttm_bo_reference(bo);
+       ret = ttm_base_object_init(tfile, &user_bo->base,
+                                  flags & TTM_PL_FLAG_SHARED,
+                                  ttm_buffer_type,
+                                  &ttm_bo_user_release,
+                                  &ttm_bo_user_ref_release);
+       if (unlikely(ret != 0))
+               goto out_err;
+
+       spin_lock(&bo->bdev->fence_lock);
+       ttm_pl_fill_rep(bo, rep);
+       spin_unlock(&bo->bdev->fence_lock);
+       ttm_bo_unref(&bo);
+out:
+       return 0;
+out_err:
+       ttm_bo_unref(&tmp);
+       ttm_bo_unref(&bo);
+       return ret;
+}
+
+int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data)
+{
+       union ttm_pl_reference_arg *arg = data;
+       struct ttm_pl_rep *rep = &arg->rep;
+       struct ttm_bo_user_object *user_bo;
+       struct ttm_buffer_object *bo;
+       struct ttm_base_object *base;
+       int ret;
+
+       user_bo = ttm_bo_user_lookup(tfile, arg->req.handle);
+       if (unlikely(user_bo == NULL)) {
+               printk(KERN_ERR "Could not reference buffer object.\n");
+               return -EINVAL;
+       }
+
+       bo = &user_bo->bo;
+       ret = ttm_ref_object_add(tfile, &user_bo->base, TTM_REF_USAGE, NULL);
+       if (unlikely(ret != 0)) {
+               printk(KERN_ERR
+                      "Could not add a reference to buffer object.\n");
+               goto out;
+       }
+
+       spin_lock(&bo->bdev->fence_lock);
+       ttm_pl_fill_rep(bo, rep);
+       spin_unlock(&bo->bdev->fence_lock);
+
+out:
+       base = &user_bo->base;
+       ttm_base_object_unref(&base);
+       return ret;
+}
+
+int ttm_pl_unref_ioctl(struct ttm_object_file *tfile, void *data)
+{
+       struct ttm_pl_reference_req *arg = data;
+
+       return ttm_ref_object_base_unref(tfile, arg->handle, TTM_REF_USAGE);
+}
+
+int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data)
+{
+       struct ttm_pl_synccpu_arg *arg = data;
+       struct ttm_bo_user_object *user_bo;
+       struct ttm_buffer_object *bo;
+       struct ttm_base_object *base;
+       bool existed;
+       int ret;
+
+       switch (arg->op) {
+       case TTM_PL_SYNCCPU_OP_GRAB:
+               user_bo = ttm_bo_user_lookup(tfile, arg->handle);
+               if (unlikely(user_bo == NULL)) {
+                       printk(KERN_ERR
+                              "Could not find buffer object for synccpu.\n");
+                       return -EINVAL;
+               }
+               bo = &user_bo->bo;
+               base = &user_bo->base;
+               ret = ttm_bo_synccpu_write_grab(bo,
+                                               arg->access_mode &
+                                               TTM_PL_SYNCCPU_MODE_NO_BLOCK);
+               if (unlikely(ret != 0)) {
+                       ttm_base_object_unref(&base);
+                       goto out;
+               }
+               ret = ttm_ref_object_add(tfile, &user_bo->base,
+                                        TTM_REF_SYNCCPU_WRITE, &existed);
+               if (existed || ret != 0)
+                       ttm_bo_synccpu_write_release(bo);
+               ttm_base_object_unref(&base);
+               break;
+       case TTM_PL_SYNCCPU_OP_RELEASE:
+               ret = ttm_ref_object_base_unref(tfile, arg->handle,
+                                               TTM_REF_SYNCCPU_WRITE);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+out:
+       return ret;
+}
+
+int ttm_pl_setstatus_ioctl(struct ttm_object_file *tfile,
+                          struct ttm_lock *lock, void *data)
+{
+       union ttm_pl_setstatus_arg *arg = data;
+       struct ttm_pl_setstatus_req *req = &arg->req;
+       struct ttm_pl_rep *rep = &arg->rep;
+       struct ttm_buffer_object *bo;
+       struct ttm_bo_device *bdev;
+       struct ttm_placement placement = default_placement;
+       uint32_t flags[2];
+       int ret;
+
+       bo = ttm_buffer_object_lookup(tfile, req->handle);
+       if (unlikely(bo == NULL)) {
+               printk(KERN_ERR
+                      "Could not find buffer object for setstatus.\n");
+               return -EINVAL;
+       }
+
+       bdev = bo->bdev;
+
+       ret = ttm_read_lock(lock, true);
+       if (unlikely(ret != 0))
+               goto out_err0;
+
+       ret = ttm_bo_reserve(bo, true, false, false, 0);
+       if (unlikely(ret != 0))
+               goto out_err1;
+
+       ret = ttm_bo_wait_cpu(bo, false);
+       if (unlikely(ret != 0))
+               goto out_err2;
+
+       flags[0] = req->set_placement;
+       flags[1] = req->clr_placement;
+
+       placement.num_placement = 2;
+       placement.placement = flags;
+
+       spin_lock(&bo->bdev->fence_lock);
+
+       ret = psb_ttm_bo_check_placement(bo, &placement);
+       if (unlikely(ret != 0))
+               goto out_err2;
+
+       placement.num_placement = 1;
+       flags[0] = (req->set_placement | bo->mem.placement) & ~req->clr_placement;
+
+       ret = ttm_bo_validate(bo, &placement, true, false, false);
+       if (unlikely(ret != 0))
+               goto out_err2;
+
+       ttm_pl_fill_rep(bo, rep);
+out_err2:
+       spin_unlock(&bo->bdev->fence_lock);
+       ttm_bo_unreserve(bo);
+out_err1:
+       ttm_read_unlock(lock);
+out_err0:
+       ttm_bo_unref(&bo);
+       return ret;
+}
+
+static int psb_ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible,
+                                       bool no_wait)
+{
+       int ret;
+
+       while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
+               if (no_wait)
+                       return -EBUSY;
+               else if (interruptible) {
+                       ret = wait_event_interruptible
+                             (bo->event_queue, atomic_read(&bo->reserved) == 0);
+                       if (unlikely(ret != 0))
+                               return -ERESTART;
+               } else {
+                       wait_event(bo->event_queue,
+                                  atomic_read(&bo->reserved) == 0);
+               }
+       }
+       return 0;
+}
+
+static void psb_ttm_bo_unblock_reservation(struct ttm_buffer_object *bo)
+{
+       atomic_set(&bo->reserved, 0);
+       wake_up_all(&bo->event_queue);
+}
+
+int ttm_pl_waitidle_ioctl(struct ttm_object_file *tfile, void *data)
+{
+       struct ttm_pl_waitidle_arg *arg = data;
+       struct ttm_buffer_object *bo;
+       int ret;
+
+       bo = ttm_buffer_object_lookup(tfile, arg->handle);
+       if (unlikely(bo == NULL)) {
+               printk(KERN_ERR "Could not find buffer object for waitidle.\n");
+               return -EINVAL;
+       }
+
+       ret =
+               psb_ttm_bo_block_reservation(bo, true,
+                                            arg->mode & TTM_PL_WAITIDLE_MODE_NO_BLOCK);
+       if (unlikely(ret != 0))
+               goto out;
+       spin_lock(&bo->bdev->fence_lock);
+       ret = ttm_bo_wait(bo,
+                         arg->mode & TTM_PL_WAITIDLE_MODE_LAZY,
+                         true, arg->mode & TTM_PL_WAITIDLE_MODE_NO_BLOCK);
+       spin_unlock(&bo->bdev->fence_lock);
+       psb_ttm_bo_unblock_reservation(bo);
+out:
+       ttm_bo_unref(&bo);
+       return ret;
+}
+
+int ttm_pl_verify_access(struct ttm_buffer_object *bo,
+                        struct ttm_object_file *tfile)
+{
+       struct ttm_bo_user_object *ubo;
+
+       /*
+        * Check bo subclass.
+        */
+
+       if (unlikely(bo->destroy != &ttm_bo_user_destroy))
+               return -EPERM;
+
+       ubo = container_of(bo, struct ttm_bo_user_object, bo);
+       if (likely(ubo->base.shareable || ubo->base.tfile == tfile))
+               return 0;
+
+       return -EPERM;
+}
diff --git a/drivers/staging/mrst/imgv/psb_ttm_placement_user.h b/drivers/staging/mrst/imgv/psb_ttm_placement_user.h
new file mode 100644 (file)
index 0000000..8b7068b
--- /dev/null
@@ -0,0 +1,252 @@
+/**************************************************************************
+ *
+ * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _TTM_PLACEMENT_USER_H_
+#define _TTM_PLACEMENT_USER_H_
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#else
+#include <linux/kernel.h>
+#endif
+
+#include "ttm/ttm_placement.h"
+
+#define TTM_PLACEMENT_MAJOR 0
+#define TTM_PLACEMENT_MINOR 1
+#define TTM_PLACEMENT_PL    0
+#define TTM_PLACEMENT_DATE  "080819"
+
+/**
+ * struct ttm_pl_create_req
+ *
+ * @size: The buffer object size.
+ * @placement: Flags that indicate initial acceptable
+ *  placement.
+ * @page_alignment: Required alignment in pages.
+ *
+ * Input to the TTM_BO_CREATE ioctl.
+ */
+
+struct ttm_pl_create_req {
+       uint64_t size;
+       uint32_t placement;
+       uint32_t page_alignment;
+};
+
+/**
+ * struct ttm_pl_create_ub_req
+ *
+ * @size: The buffer object size.
+ * @user_address: User-space address of the memory area that
+ * should be used to back the buffer object cast to 64-bit.
+ * @placement: Flags that indicate initial acceptable
+ *  placement.
+ * @page_alignment: Required alignment in pages.
+ *
+ * Input to the TTM_BO_CREATE_UB ioctl.
+ */
+
+struct ttm_pl_create_ub_req {
+       uint64_t size;
+       uint64_t user_address;
+       uint32_t placement;
+       uint32_t page_alignment;
+};
+
+/**
+ * struct ttm_pl_rep
+ *
+ * @gpu_offset: The current offset into the memory region used.
+ * This can be used directly by the GPU if there are no
+ * additional GPU mapping procedures used by the driver.
+ *
+ * @bo_size: Actual buffer object size.
+ *
+ * @map_handle: Offset into the device address space.
+ * Used for map, seek, read, write. This will never change
+ * during the lifetime of an object.
+ *
+ * @placement: Flag indicating the placement status of
+ * the buffer object using the TTM_PL flags above.
+ *
+ * @sync_object_arg: Used for user-space synchronization and
+ * depends on the synchronization model used. If fences are
+ * used, this is the buffer_object::fence_type_mask
+ *
+ * Output from the TTM_PL_CREATE and TTM_PL_REFERENCE, and
+ * TTM_PL_SETSTATUS ioctls.
+ */
+
+struct ttm_pl_rep {
+       uint64_t gpu_offset;
+       uint64_t bo_size;
+       uint64_t map_handle;
+       uint32_t placement;
+       uint32_t handle;
+       uint32_t sync_object_arg;
+       uint32_t pad64;
+};
+
+/**
+ * struct ttm_pl_setstatus_req
+ *
+ * @set_placement: Placement flags to set.
+ *
+ * @clr_placement: Placement flags to clear.
+ *
+ * @handle: The object handle
+ *
+ * Input to the TTM_PL_SETSTATUS ioctl.
+ */
+
+struct ttm_pl_setstatus_req {
+       uint32_t set_placement;
+       uint32_t clr_placement;
+       uint32_t handle;
+       uint32_t pad64;
+};
+
+/**
+ * struct ttm_pl_reference_req
+ *
+ * @handle: The object to put a reference on.
+ *
+ * Input to the TTM_PL_REFERENCE and the TTM_PL_UNREFERENCE ioctls.
+ */
+
+struct ttm_pl_reference_req {
+       uint32_t handle;
+       uint32_t pad64;
+};
+
+/*
+ * ACCESS mode flags for SYNCCPU.
+ *
+ * TTM_SYNCCPU_MODE_READ will guarantee that the GPU is not
+ * writing to the buffer.
+ *
+ * TTM_SYNCCPU_MODE_WRITE will guarantee that the GPU is not
+ * accessing the buffer.
+ *
+ * TTM_SYNCCPU_MODE_NO_BLOCK makes sure the call does not wait
+ * for GPU accesses to finish but return -EBUSY.
+ *
+ * TTM_SYNCCPU_MODE_TRYCACHED Try to place the buffer in cacheable
+ * memory while synchronized for CPU.
+ */
+
+#define TTM_PL_SYNCCPU_MODE_READ      TTM_ACCESS_READ
+#define TTM_PL_SYNCCPU_MODE_WRITE     TTM_ACCESS_WRITE
+#define TTM_PL_SYNCCPU_MODE_NO_BLOCK  (1 << 2)
+#define TTM_PL_SYNCCPU_MODE_TRYCACHED (1 << 3)
+
+/**
+ * struct ttm_pl_synccpu_arg
+ *
+ * @handle: The object to synchronize.
+ *
+ * @access_mode: access mode indicated by the
+ * TTM_SYNCCPU_MODE flags.
+ *
+ * @op: indicates whether to grab or release the
+ * buffer for cpu usage.
+ *
+ * Input to the TTM_PL_SYNCCPU ioctl.
+ */
+
+struct ttm_pl_synccpu_arg {
+       uint32_t handle;
+       uint32_t access_mode;
+       enum {
+               TTM_PL_SYNCCPU_OP_GRAB,
+               TTM_PL_SYNCCPU_OP_RELEASE
+       } op;
+       uint32_t pad64;
+};
+
+/*
+ * Waiting mode flags for the TTM_BO_WAITIDLE ioctl.
+ *
+ * TTM_WAITIDLE_MODE_LAZY: Allow for sleeps during polling
+ * wait.
+ *
+ * TTM_WAITIDLE_MODE_NO_BLOCK: Don't block waiting for GPU,
+ * but return -EBUSY if the buffer is busy.
+ */
+
+#define TTM_PL_WAITIDLE_MODE_LAZY     (1 << 0)
+#define TTM_PL_WAITIDLE_MODE_NO_BLOCK (1 << 1)
+
+/**
+ * struct ttm_waitidle_arg
+ *
+ * @handle: The object to synchronize.
+ *
+ * @mode: wait mode indicated by the
+ * TTM_SYNCCPU_MODE flags.
+ *
+ * Argument to the TTM_BO_WAITIDLE ioctl.
+ */
+
+struct ttm_pl_waitidle_arg {
+       uint32_t handle;
+       uint32_t mode;
+};
+
+union ttm_pl_create_arg {
+       struct ttm_pl_create_req req;
+       struct ttm_pl_rep rep;
+};
+
+union ttm_pl_reference_arg {
+       struct ttm_pl_reference_req req;
+       struct ttm_pl_rep rep;
+};
+
+union ttm_pl_setstatus_arg {
+       struct ttm_pl_setstatus_req req;
+       struct ttm_pl_rep rep;
+};
+
+union ttm_pl_create_ub_arg {
+       struct ttm_pl_create_ub_req req;
+       struct ttm_pl_rep rep;
+};
+
+/*
+ * Ioctl offsets.
+ */
+
+#define TTM_PL_CREATE      0x00
+#define TTM_PL_REFERENCE   0x01
+#define TTM_PL_UNREF       0x02
+#define TTM_PL_SYNCCPU     0x03
+#define TTM_PL_WAITIDLE    0x04
+#define TTM_PL_SETSTATUS   0x05
+#define TTM_PL_CREATE_UB   0x06
+
+#endif
diff --git a/drivers/staging/mrst/imgv/psb_ttm_userobj_api.h b/drivers/staging/mrst/imgv/psb_ttm_userobj_api.h
new file mode 100644 (file)
index 0000000..07bb656
--- /dev/null
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _TTM_USEROBJ_API_H_
+#define _TTM_USEROBJ_API_H_
+
+#include "psb_ttm_placement_user.h"
+#include "psb_ttm_fence_user.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_api.h"
+#include "ttm/ttm_bo_api.h"
+
+struct ttm_lock;
+
+/*
+ * User ioctls.
+ */
+
+extern int ttm_pl_create_ioctl(struct ttm_object_file *tfile,
+                              struct ttm_bo_device *bdev,
+                              struct ttm_lock *lock, void *data);
+extern int ttm_pl_ub_create_ioctl(struct ttm_object_file *tfile,
+                                 struct ttm_bo_device *bdev,
+                                 struct ttm_lock *lock, void *data);
+extern int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_unref_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_setstatus_ioctl(struct ttm_object_file *tfile,
+                                 struct ttm_lock *lock, void *data);
+extern int ttm_pl_waitidle_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_signaled_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_finish_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_unref_ioctl(struct ttm_object_file *tfile, void *data);
+
+extern int
+ttm_fence_user_create(struct ttm_fence_device *fdev,
+                     struct ttm_object_file *tfile,
+                     uint32_t fence_class,
+                     uint32_t fence_types,
+                     uint32_t create_flags,
+                     struct ttm_fence_object **fence, uint32_t * user_handle);
+
+extern struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file
+               *tfile,
+               uint32_t handle);
+
+extern int
+ttm_pl_verify_access(struct ttm_buffer_object *bo,
+                    struct ttm_object_file *tfile);
+
+extern int ttm_buffer_object_create(struct ttm_bo_device *bdev,
+                                   unsigned long size,
+                                   enum ttm_bo_type type,
+                                   uint32_t flags,
+                                   uint32_t page_alignment,
+                                   unsigned long buffer_start,
+                                   bool interruptible,
+                                   struct file *persistant_swap_storage,
+                                   struct ttm_buffer_object **p_bo);
+
+extern int psb_ttm_bo_check_placement(struct ttm_buffer_object *bo,
+                                     struct ttm_placement *placement);
+#endif
diff --git a/drivers/staging/mrst/imgv/topaz_power.c b/drivers/staging/mrst/imgv/topaz_power.c
new file mode 100644 (file)
index 0000000..ec3c387
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author:binglin.chen@intel.com
+ */
+
+#include "topaz_power.h"
+#include "pnw_topaz.h"
+#include "psb_drv.h"
+#include "services_headers.h"
+#include "sysconfig.h"
+#include "psb_powermgmt.h"
+
+static PVRSRV_ERROR DevInitTOPAZPart1(IMG_VOID *pvDeviceNode)
+{
+#if 1
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+       PVRSRV_ERROR eError;
+       PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+
+       /* register power operation function */
+       /* FIXME: this should be in part2 init function, but
+        * currently here only OSPM needs IMG device... */
+       eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+       eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
+                                          TOPAZPrePowerState,
+                                          TOPAZPostPowerState,
+                                          TOPAZPreClockSpeedChange,
+                                          TOPAZPostClockSpeedChange,
+                                          (IMG_HANDLE)psDeviceNode,
+                                          PVRSRV_DEV_POWER_STATE_ON,
+                                          eDefaultPowerState);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR, "DevInitTOPAZPart1: failed to "
+                        "register device with power manager"));
+               return eError;
+       }
+#endif
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DevDeInitTOPAZ(IMG_VOID *pvDeviceNode)
+{
+#if 1
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+       PVRSRV_ERROR eError;
+
+       /* should deinit all resource */
+
+       eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
+       if (eError != PVRSRV_OK)
+               return eError;
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       /* version check */
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       psDeviceNode->sDevId.eDeviceType        = PVRSRV_DEVICE_TYPE_TOPAZ;
+       psDeviceNode->sDevId.eDeviceClass       = PVRSRV_DEVICE_CLASS_VIDEO;
+
+       psDeviceNode->pfnInitDevice             = DevInitTOPAZPart1;
+       psDeviceNode->pfnDeInitDevice           = DevDeInitTOPAZ;
+
+       psDeviceNode->pfnInitDeviceCompatCheck  = TOPAZDevInitCompatCheck;
+
+       psDeviceNode->pfnDeviceISR = pnw_topaz_interrupt;
+       psDeviceNode->pvISRData = (IMG_VOID *)gpDrmDevice;
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZPrePowerState(IMG_HANDLE             hDevHandle,
+                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState)
+{
+#if 1
+       /* ask for a change not power on*/
+       if ((eNewPowerState != eCurrentPowerState) &&
+           (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+               struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+               struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+               PNW_TOPAZ_NEW_PMSTATE(gpDrmDevice, topaz_priv, PSB_PMSTATE_POWERDOWN);
+
+               /* context save */
+               /* context save require irq disable first */
+               psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+               pnw_topaz_save_mtx_state(gpDrmDevice);
+
+               /* internally close the device */
+
+               /* ask for power off */
+               if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+                       /* here will deinitialize the driver if needed */
+                       /* FIXME: according to latest topaz runtime_pm suspend/resume
+                        *        6f78a5b61be55d222fa3880008d2198efa7713bf by Austin, Yuan
+                        *        1) Remove map_topaz_reg/unmap_topaz_reg for suspend/resume
+                        *        no map/umap topaz register is needed */
+                       //pnw_unmap_topaz_reg(gpDrmDevice);
+               } else {
+                       PVR_DPF((PVR_DBG_MESSAGE,
+                                       "%s no action for transform from %d to %d",
+                                       __func__,
+                                       eCurrentPowerState,
+                                       eNewPowerState));
+               }
+       }
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZPostPowerState(IMG_HANDLE            hDevHandle,
+                                PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+#if 1
+       /* if ask for change & current status is not on */
+       if ((eNewPowerState != eCurrentPowerState) &&
+           (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+               /* internally open device */
+               struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+               struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+               PNW_TOPAZ_NEW_PMSTATE(gpDrmDevice, topaz_priv, PSB_PMSTATE_POWERUP);
+
+               if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+                       /* here will initialize the driver if needed */
+                       /* FIXME: according to latest topaz runtime_pm suspend/resume
+                        *        6f78a5b61be55d222fa3880008d2198efa7713bf by Austin, Yuan
+                        *        1) Remove map_topaz_reg/unmap_topaz_reg for suspend/resume
+                        *        no map/umap topaz register is needed */
+                       //pnw_map_topaz_reg(gpDrmDevice);
+               } else {
+                       PVR_DPF((PVR_DBG_MESSAGE,
+                                       "%s no action for transform from %d to %d",
+                                       __func__,
+                                       eCurrentPowerState,
+                                       eNewPowerState));
+               }
+
+               /* context restore */
+               psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+               pnw_topaz_restore_mtx_state(gpDrmDevice);
+               psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+               psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+       }
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZPreClockSpeedChange(IMG_HANDLE       hDevHandle,
+                                     IMG_BOOL          bIdleDevice,
+                                     PVRSRV_DEV_POWER_STATE    eCurrentPowerState)
+{
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZPostClockSpeedChange(IMG_HANDLE      hDevHandle,
+                                      IMG_BOOL         bIdleDevice,
+                                      PVRSRV_DEV_POWER_STATE   eCurrentPowerState)
+{
+       return PVRSRV_OK;
+}
diff --git a/drivers/staging/mrst/imgv/topaz_power.h b/drivers/staging/mrst/imgv/topaz_power.h
new file mode 100644 (file)
index 0000000..3ffecb0
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+** topaz_power.h
+** Login : <binglin.chen@intel.com>
+** Started on  Mon Nov 16 13:31:42 2009 brady
+**
+** Copyright (C) 2009 brady
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef TOPAZ_POWER_H_
+#define TOPAZ_POWER_H_
+
+#include "services_headers.h"
+#include "sysconfig.h"
+
+/* function define */
+PVRSRV_ERROR TOPAZRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+PVRSRV_ERROR TOPAZDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/* power function define */
+PVRSRV_ERROR TOPAZPrePowerState(
+       IMG_HANDLE              hDevHandle,
+       PVRSRV_DEV_POWER_STATE  eNewPowerState,
+       PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+PVRSRV_ERROR TOPAZPostPowerState(
+       IMG_HANDLE              hDevHandle,
+       PVRSRV_DEV_POWER_STATE  eNewPowerState,
+       PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+PVRSRV_ERROR TOPAZPreClockSpeedChange(
+       IMG_HANDLE              hDevHandle,
+       IMG_BOOL                bIdleDevice,
+       PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+PVRSRV_ERROR TOPAZPostClockSpeedChange(
+       IMG_HANDLE              hDevHandle,
+       IMG_BOOL                bIdleDevice,
+       PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+PVRSRV_ERROR TOPAZInitOSPM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#endif /* !TOPAZ_POWER_H_ */
diff --git a/drivers/staging/mrst/medfield/Makefile b/drivers/staging/mrst/medfield/Makefile
new file mode 100644 (file)
index 0000000..f9aa9dc
--- /dev/null
@@ -0,0 +1,207 @@
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+INCDIR=drivers/staging/mrst
+
+include_dirs := \
+       -I$(INCDIR)/pvr \
+       -I$(INCDIR)/pvr/include4 \
+        -I$(INCDIR)/pvr/services4/include \
+        -I$(INCDIR)/pvr/services4/include/env/linux \
+        -I$(INCDIR)/pvr/services4/3rdparty/linux_framebuffer_mrst \
+        -I$(INCDIR)/pvr/services4/srvkm/env/linux \
+        -I$(INCDIR)/pvr/services4/srvkm/include \
+        -I$(INCDIR)/pvr/services4/srvkm/bridged \
+        -I$(INCDIR)/pvr/services4/srvkm/common \
+        -I$(INCDIR)/pvr/services4/system/include \
+        -I$(INCDIR)/pvr/services4/srvkm/hwdefs \
+        -I$(INCDIR)/pvr/services4/srvkm/bridged/sgx \
+        -I$(INCDIR)/pvr/services4/srvkm/devices/sgx \
+        -I$(INCDIR)/ \
+        -I$(INCDIR)/drv \
+        -I$(INCDIR)/bc_video \
+        -I$(INCDIR)/imgv \
+       -Iinclude/linux \
+       -Iinclude/drm
+
+ccflags-y += $(include_dirs)
+ccflags-y += -I$(INCDIR)/pvr/services4/system/unified -DSGX540 -DSUPPORT_SGX540 -DSGX_CORE_REV=121
+
+ccflags-y += \
+       -DLINUX \
+       -DPVR_BUILD_DIR="\"pc_i686_moorestown_linux\"" \
+       -DSERVICES4 \
+       -D_XOPEN_SOURCE=600 \
+       -DPVR2D_VALIDATE_INPUT_PARAMS \
+       -DDISPLAY_CONTROLLER=mrstlfb \
+       -UDEBUG_LOG_PATH_TRUNCATE \
+       -DSUPPORT_SRVINIT \
+       -DSUPPORT_SGX \
+       -DSUPPORT_LINUX_X86_WRITECOMBINE \
+       -DTRANSFER_QUEUE \
+       -DSUPPORT_DRI_DRM \
+       -DSUPPORT_DRI_DRM_EXT \
+       -DSYS_USING_INTERRUPTS \
+       -DSUPPORT_HW_RECOVERY \
+       -DSUPPORT_ACTIVE_POWER_MANAGEMENT \
+       -DPVR_SECURE_HANDLES \
+       -DUSE_PTHREADS \
+       -DSUPPORT_SGX_EVENT_OBJECT \
+       -DSUPPORT_SGX_HWPERF \
+       -DSUPPORT_SGX_LOW_LATENCY_SCHEDULING \
+       -DSUPPORT_LINUX_X86_PAT \
+       -DPVR_PROC_USE_SEQ_FILE \
+       -DSUPPORT_CACHE_LINE_FLUSH \
+       -DSUPPORT_CPU_CACHED_BUFFERS \
+       -DDEBUG_MESA_OGL_TRACE \
+       -DDISABLE_PM \
+       -DSUPPORT_SGX_NEW_STATUS_VALS \
+       -DSUPPORT_PERCONTEXT_PB \
+       -DDRM_PVR_USE_INTEL_FB  \
+       -DSUPPORT_MEMINFO_IDS
+
+GL3_EXTERNAL_SYSTEM_CACHE ?=0
+ifeq ($(GL3_EXTERNAL_SYSTEM_CACHE),1)
+   SUPPORT_EXTERNAL_SYSTEM_CACHE = y
+   CONFIG_MDFD_GL3 = y
+else
+   SUPPORT_EXTERNAL_SYSTEM_CACHE =
+   CONFIG_MDFD_GL3 =
+endif
+ccflags-$(SUPPORT_EXTERNAL_SYSTEM_CACHE) += -DSUPPORT_EXTERNAL_SYSTEM_CACHE -DCONFIG_MDFD_GL3
+
+PVRSRV_RESOURCE_PROFILING =
+PERPROC_LIST =
+RES_MAN_EXTEND =
+PVRSRV_OS_MEM_INFO =
+
+ccflags-$(PVRSRV_RESOURCE_PROFILING) += -DPVRSRV_RESOURCE_PROFILING
+ccflags-$(PERPROC_LIST) += -DPERPROC_LIST
+ccflags-$(RES_MAN_EXTEND) += -DRES_MAN_EXTEND
+ccflags-$(PVRSRV_OS_MEM_INFO) += -DPVRSRV_OS_MEM_INFO
+
+ccflags-$(CONFIG_DRM_MID_RELEASE) += -DBUILD="\"release\"" -DPVR_BUILD_TYPE="\"release\"" -DRELEASE
+ccflags-$(CONFIG_DRM_MID_DEBUG) += -DBUILD="\"debug\"" -DPVR_BUILD_TYPE="\"debug\"" -DDEBUG -DDEBUG_LINUX_MEM_AREAS -DDEBUG_LINUX_MEMORY_ALLOCATIONS -DDEBUG_LINUX_MMAP_AREAS -DDEBUG_BRIDGE_KM
+ccflags-$(CONFIG_PCI_MSI) += -DCONFIG_PCI_MSI
+
+PVRDIR = ../pvr
+ENVDIR = ../pvr/services4/srvkm/env/linux
+COMMONDIR = ../pvr/services4/srvkm/common
+BRIDGEDDIR = ../pvr/services4/srvkm/bridged
+SGXDIR = ../pvr/services4/srvkm/devices/sgx
+FBDEVDIR = ../pvr/services4/3rdparty/linux_framebuffer_mrst
+DRMDRVDIR = ../drv
+SYSCONFIGDIR = ../pvr/services4/system/unified
+IMGVDIR = ../imgv
+BUFFER_CLASS_DIR = ../bc_video
+
+medfield_gfx-y += $(ENVDIR)/osfunc.o \
+         $(ENVDIR)/ossync.o \
+         $(ENVDIR)/mutils.o \
+         $(ENVDIR)/mmap.o \
+         $(ENVDIR)/module.o \
+         $(ENVDIR)/pdump.o \
+         $(ENVDIR)/proc.o \
+         $(ENVDIR)/pvr_bridge_k.o \
+         $(ENVDIR)/pvr_debug.o \
+         $(ENVDIR)/mm.o \
+         $(ENVDIR)/mutex.o \
+         $(ENVDIR)/event.o \
+         $(ENVDIR)/osperproc.o \
+         $(ENVDIR)/pvr_drm.o
+
+medfield_gfx-y += $(COMMONDIR)/buffer_manager.o \
+         $(COMMONDIR)/devicemem.o \
+         $(COMMONDIR)/deviceclass.o \
+         $(COMMONDIR)/handle.o \
+         $(COMMONDIR)/hash.o \
+         $(COMMONDIR)/metrics.o \
+         $(COMMONDIR)/pvrsrv.o \
+         $(COMMONDIR)/queue.o \
+         $(COMMONDIR)/ra.o \
+         $(COMMONDIR)/resman.o \
+         $(COMMONDIR)/power.o \
+         $(COMMONDIR)/mem.o \
+         $(COMMONDIR)/pdump_common.o \
+         $(COMMONDIR)/perproc.o \
+         $(COMMONDIR)/lists.o \
+         $(COMMONDIR)/mem_debug.o \
+         $(COMMONDIR)/osfunc_common.o
+
+medfield_gfx-y += $(BRIDGEDDIR)/bridged_support.o \
+         $(BRIDGEDDIR)/bridged_pvr_bridge.o \
+         $(BRIDGEDDIR)/sgx/bridged_sgx_bridge.o
+
+medfield_gfx-y += $(SYSCONFIGDIR)/sysconfig.o \
+         $(SYSCONFIGDIR)/sysutils.o \
+         $(SYSCONFIGDIR)/sys_pvr_drm_export.o
+
+medfield_gfx-y += $(SGXDIR)/sgxinit.o \
+         $(SGXDIR)/sgxpower.o \
+         $(SGXDIR)/sgxreset.o \
+         $(SGXDIR)/sgxutils.o \
+         $(SGXDIR)/sgxkick.o \
+         $(SGXDIR)/sgxtransfer.o \
+         $(SGXDIR)/mmu.o \
+         $(SGXDIR)/pb.o
+
+medfield_gfx-y += $(FBDEVDIR)/mrstlfb_displayclass.o \
+         $(FBDEVDIR)/mrstlfb_linux.o
+
+medfield_gfx-y += $(DRMDRVDIR)/psb_bl.o \
+         $(DRMDRVDIR)/psb_dpst.o \
+         $(DRMDRVDIR)/psb_drv.o \
+         $(DRMDRVDIR)/psb_fb.o \
+         $(DRMDRVDIR)/psb_gtt.o \
+         $(DRMDRVDIR)/psb_hotplug.o \
+         $(DRMDRVDIR)/psb_intel_display.o \
+         $(DRMDRVDIR)/psb_page_flip.o \
+         $(DRMDRVDIR)/mdfld_hdmi_audio.o \
+         $(DRMDRVDIR)/mdfld_msic.o \
+         $(DRMDRVDIR)/mdfld_intel_hdcp.o \
+         $(DRMDRVDIR)/psb_intel_hdmi.o \
+         $(DRMDRVDIR)/psb_intel_hdmi_i2c.o \
+         $(DRMDRVDIR)/psb_reset.o \
+         $(DRMDRVDIR)/psb_schedule.o \
+         $(DRMDRVDIR)/psb_sgx.o \
+         $(DRMDRVDIR)/psb_socket.o \
+         $(DRMDRVDIR)/psb_pvr_glue.o \
+         $(DRMDRVDIR)/psb_umevents.o \
+         $(DRMDRVDIR)/mdfld_dsi_dbi.o \
+         $(DRMDRVDIR)/mdfld_dsi_dpi.o \
+         $(DRMDRVDIR)/mdfld_dsi_output.o \
+         $(DRMDRVDIR)/mdfld_output.o \
+         $(DRMDRVDIR)/tpo_cmd.o \
+         $(DRMDRVDIR)/tpo_vid.o \
+         $(DRMDRVDIR)/tmd_vid.o \
+         $(DRMDRVDIR)/tc35876x-dsi-lvds.o \
+         $(DRMDRVDIR)/mdfld_dsi_pkg_sender.o
+
+medfield_gfx-y += \
+         $(IMGVDIR)/topaz_power.o \
+         $(IMGVDIR)/pnw_topaz.o \
+         $(IMGVDIR)/pnw_topazinit.o \
+         $(IMGVDIR)/psb_buffer.o \
+         $(IMGVDIR)/psb_fence.o \
+         $(IMGVDIR)/psb_mmu.o \
+         $(IMGVDIR)/psb_msvdx.o \
+         $(IMGVDIR)/msvdx_power.o \
+         $(IMGVDIR)/psb_msvdxinit.o \
+         $(IMGVDIR)/psb_ttm_glue.o \
+         $(IMGVDIR)/psb_ttm_fence.o \
+         $(IMGVDIR)/psb_ttm_fence_user.o \
+         $(IMGVDIR)/psb_ttm_placement_user.o
+
+medfield_gfx-$(CONFIG_MDFLD_DSI_DPU) += $(DRMDRVDIR)/mdfld_dsi_dbi_dpu.o
+
+medfield_gfx-$(CONFIG_MDFD_GL3) += $(DRMDRVDIR)/mdfld_gl3.o
+
+medfield_gfx-$(CONFIG_DEBUG_FS) += $(PVRDIR)/pvr_debugfs.o
+medfield_gfx-$(CONFIG_PVR_TRACE_CMD) += $(PVRDIR)/pvr_trace_cmd.o
+
+medfield_gfx-y += $(DRMDRVDIR)/psb_powermgmt.o $(DRMDRVDIR)/psb_irq.o
+
+medfield_gfx-y += $(BUFFER_CLASS_DIR)/bufferclass_video.o \
+       $(BUFFER_CLASS_DIR)/bufferclass_video_linux.o
+
+obj-$(CONFIG_DRM_MDFLD) += medfield_gfx.o
diff --git a/drivers/staging/mrst/pvr/COPYING b/drivers/staging/mrst/pvr/COPYING
new file mode 100644 (file)
index 0000000..80dd76b
--- /dev/null
@@ -0,0 +1,351 @@
+
+This software is Copyright (C) 2008 Imagination Technologies Ltd.
+                       All rights reserved.
+
+You may use, distribute and copy this software under the terms of
+GNU General Public License version 2, which is displayed below.
+
+-------------------------------------------------------------------------
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
+
diff --git a/drivers/staging/mrst/pvr/INSTALL b/drivers/staging/mrst/pvr/INSTALL
new file mode 100644 (file)
index 0000000..e4c1069
--- /dev/null
@@ -0,0 +1,76 @@
+
+SGX Embedded Systems DDK for the Linux kernel.
+Copyright (C) 2008 Imagination Technologies Ltd. All rights reserved.
+======================================================================
+
+This file covers how to build and install the Imagination Technologies
+SGX DDK for the Linux kernel.
+
+
+Build System Environment Variables
+-------------------------------------------
+
+The SGX DDK Build scripts depend on a number of environment variables
+being setup before compilation or installation of DDK software can
+commence:
+
+$DISCIMAGE
+The DDK Build scripts install files to the location specified by the
+DISCIMAGE environment variable, when the make install target is used.
+This should point to the target filesystem.
+$ export DISCIMAGE=/path/to/filesystem
+
+$KERNELDIR
+When building the SGX DDK kernel module, the build needs access
+to the headers of the Linux kernel
+$ export KERNELDIR=/path/to/kernel
+
+$PATH
+If a cross compiler is being used make sure the PATH environment variable
+includes the path to the toolchain
+$ export PATH=$PATH:/path/to/toolchain
+
+$CROSS_COMPILE
+Since the SGX DDK Build scripts are geared toward a cross-compilation
+workflow, the CROSS_COMPILE environment variable needs to be set
+$ export CROSS_COMPILE=toolchain-prefix-
+
+
+Build and Install Instructions
+-------------------------------------------
+
+The SGX DDK configures different target builds within directories under
+eurasiacon/build/linux/.
+
+The supported build targets are:
+
+       all             Makes everything
+       clean   Removes all intermediate files created by a build.
+       clobber Removes all binaries for all builds as well.
+       install Runs the install script generated by the build.
+
+The following variables may be set on the command line to influence a build.
+
+       BUILD   The type of build being performed.
+                       Alternatives are release, timing or debug.
+       CFLAGS  Build dependent optimisations and debug information flags.
+       SILENT  Determines whether text of commands is produced during build.
+
+To build for, change to the appropriate target directory, e.g.:
+$ cd eurasiacon/build/linux/platform/kbuild
+
+Issue the make command:
+$ make BUILD=debug all
+
+The DDK software must be installed by the root user.  Become the root user:
+$ su
+
+Install the DDK software:
+$ make install
+
+Become an ordinary user again:
+$ exit
+
+
+
+
diff --git a/drivers/staging/mrst/pvr/README b/drivers/staging/mrst/pvr/README
new file mode 100644 (file)
index 0000000..8039c39
--- /dev/null
@@ -0,0 +1,48 @@
+
+SGX Embedded Systems DDK for Linux kernel.
+Copyright (C) 2008 Imagination Technologies Ltd. All rights reserved.
+======================================================================
+
+
+About
+-------------------------------------------
+
+This is the Imagination Technologies SGX DDK for the Linux kernel.
+
+
+License
+-------------------------------------------
+
+You may use, distribute and copy this software under the terms of
+GNU General Public License version 2.
+
+The full GNU General Public License version 2 is included in this
+distribution in the file called "COPYING".
+
+
+Build and Install Instructions
+-------------------------------------------
+
+For details see the "INSTALL" file.
+
+To build for, change to the appropriate target directory, e.g.:
+$ cd eurasiacon/build/linux/platform/kbuild
+
+Issue the make command:
+$ make BUILD=debug all
+
+The DDK software must be installed by the root user.  Become the root user:
+$ su
+
+Install the DDK software:
+$ make install
+
+Become an ordinary user again:
+$ exit
+
+
+Contact information:
+-------------------------------------------
+
+Imagination Technologies Ltd. <gpl-support@imgtec.com>
+Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
diff --git a/drivers/staging/mrst/pvr/eurasiacon/.gitignore b/drivers/staging/mrst/pvr/eurasiacon/.gitignore
new file mode 100644 (file)
index 0000000..f558f8b
--- /dev/null
@@ -0,0 +1,6 @@
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+binary_pc_i686*
+*.o
+*.o.cmd
diff --git a/drivers/staging/mrst/pvr/include4/dbgdrvif.h b/drivers/staging/mrst/pvr/include4/dbgdrvif.h
new file mode 100644 (file)
index 0000000..132aac8
--- /dev/null
@@ -0,0 +1,312 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _DBGDRVIF_
+#define _DBGDRVIF_
+
+
+#include "ioctldef.h"
+
+#define DEBUG_CAPMODE_FRAMED                   0x00000001UL
+#define DEBUG_CAPMODE_CONTINUOUS               0x00000002UL
+#define DEBUG_CAPMODE_HOTKEY                   0x00000004UL
+
+#define DEBUG_OUTMODE_STANDARDDBG              0x00000001UL
+#define DEBUG_OUTMODE_MONO                             0x00000002UL
+#define DEBUG_OUTMODE_STREAMENABLE             0x00000004UL
+#define DEBUG_OUTMODE_ASYNC                            0x00000008UL
+#define DEBUG_OUTMODE_SGXVGA            0x00000010UL
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM   0x00000001UL
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION  0x00000002UL
+#define DEBUG_FLAGS_ENABLESAMPLE               0x00000004UL
+#define DEBUG_FLAGS_READONLY                   0x00000008UL
+#define DEBUG_FLAGS_WRITEONLY                  0x00000010UL
+
+#define DEBUG_FLAGS_TEXTSTREAM                 0x80000000UL
+
+#define DEBUG_LEVEL_0                                  0x00000001UL
+#define DEBUG_LEVEL_1                                  0x00000003UL
+#define DEBUG_LEVEL_2                                  0x00000007UL
+#define DEBUG_LEVEL_3                                  0x0000000FUL
+#define DEBUG_LEVEL_4                                  0x0000001FUL
+#define DEBUG_LEVEL_5                                  0x0000003FUL
+#define DEBUG_LEVEL_6                                  0x0000007FUL
+#define DEBUG_LEVEL_7                                  0x000000FFUL
+#define DEBUG_LEVEL_8                                  0x000001FFUL
+#define DEBUG_LEVEL_9                                  0x000003FFUL
+#define DEBUG_LEVEL_10                                 0x000007FFUL
+#define DEBUG_LEVEL_11                                 0x00000FFFUL
+
+#define DEBUG_LEVEL_SEL0                               0x00000001UL
+#define DEBUG_LEVEL_SEL1                               0x00000002UL
+#define DEBUG_LEVEL_SEL2                               0x00000004UL
+#define DEBUG_LEVEL_SEL3                               0x00000008UL
+#define DEBUG_LEVEL_SEL4                               0x00000010UL
+#define DEBUG_LEVEL_SEL5                               0x00000020UL
+#define DEBUG_LEVEL_SEL6                               0x00000040UL
+#define DEBUG_LEVEL_SEL7                               0x00000080UL
+#define DEBUG_LEVEL_SEL8                               0x00000100UL
+#define DEBUG_LEVEL_SEL9                               0x00000200UL
+#define DEBUG_LEVEL_SEL10                              0x00000400UL
+#define DEBUG_LEVEL_SEL11                              0x00000800UL
+
+#define DEBUG_SERVICE_IOCTL_BASE               0x800UL
+#define DEBUG_SERVICE_CREATESTREAM             CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DESTROYSTREAM            CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSTREAM                        CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRING              CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READSTRING               CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE                            CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READ                             CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGMODE             CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGOUTMODE  CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGLEVEL            CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0A, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETFRAME                 CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0B, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETFRAME                 CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0C, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_OVERRIDEMODE             CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0D, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DEFAULTMODE              CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0E, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSERVICETABLE  CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0F, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE2                   CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRINGCM            CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x11, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITECM                  CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x12, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETMARKER                        CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x13, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETMARKER                        CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x14, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_ISCAPTUREFRAME   CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x15, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITELF                  CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x16, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READLF                   CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x17, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WAITFOREVENT             CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x18, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETCONNNOTIFY            CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x19, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+typedef enum _DBG_EVENT_
+{
+       DBG_EVENT_STREAM_DATA = 1
+} DBG_EVENT;
+
+
+typedef struct _DBG_IN_CREATESTREAM_
+{
+       union
+       {
+               IMG_CHAR *pszName;
+               IMG_UINT64 ui64Name;
+       } u;
+       IMG_UINT32 ui32Pages;
+       IMG_UINT32 ui32CapMode;
+       IMG_UINT32 ui32OutMode;
+}DBG_IN_CREATESTREAM, *PDBG_IN_CREATESTREAM;
+
+typedef struct _DBG_IN_FINDSTREAM_
+{
+       union
+       {
+               IMG_CHAR *pszName;
+               IMG_UINT64 ui64Name;
+       }u;
+       IMG_BOOL bResetStream;
+}DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
+
+typedef struct _DBG_IN_WRITESTRING_
+{
+       union
+       {
+               IMG_CHAR *pszString;
+               IMG_UINT64 ui64String;
+       } u;
+       IMG_SID hStream;
+       IMG_UINT32 ui32Level;
+}DBG_IN_WRITESTRING, *PDBG_IN_WRITESTRING;
+
+typedef struct _DBG_IN_READSTRING_
+{
+       union
+       {
+               IMG_CHAR *pszString;
+               IMG_UINT64 ui64String;
+       } u;
+       IMG_SID hStream;
+       IMG_UINT32 ui32StringLen;
+} DBG_IN_READSTRING, *PDBG_IN_READSTRING;
+
+typedef struct _DBG_IN_SETDEBUGMODE_
+{
+       IMG_SID hStream;
+       IMG_UINT32 ui32Mode;
+       IMG_UINT32 ui32Start;
+       IMG_UINT32 ui32End;
+       IMG_UINT32 ui32SampleRate;
+} DBG_IN_SETDEBUGMODE, *PDBG_IN_SETDEBUGMODE;
+
+typedef struct _DBG_IN_SETDEBUGOUTMODE_
+{
+       IMG_SID hStream;
+       IMG_UINT32 ui32Mode;
+} DBG_IN_SETDEBUGOUTMODE, *PDBG_IN_SETDEBUGOUTMODE;
+
+typedef struct _DBG_IN_SETDEBUGLEVEL_
+{
+       IMG_SID hStream;
+       IMG_UINT32 ui32Level;
+} DBG_IN_SETDEBUGLEVEL, *PDBG_IN_SETDEBUGLEVEL;
+
+typedef struct _DBG_IN_SETFRAME_
+{
+       IMG_SID hStream;
+       IMG_UINT32 ui32Frame;
+} DBG_IN_SETFRAME, *PDBG_IN_SETFRAME;
+
+typedef struct _DBG_IN_WRITE_
+{
+       union
+       {
+               IMG_UINT8 *pui8InBuffer;
+               IMG_UINT64 ui64InBuffer;
+       } u;
+       IMG_SID hStream;
+       IMG_UINT32 ui32Level;
+       IMG_UINT32 ui32TransferSize;
+} DBG_IN_WRITE, *PDBG_IN_WRITE;
+
+typedef struct _DBG_IN_READ_
+{
+       union
+       {
+               IMG_UINT8 *pui8OutBuffer;
+               IMG_UINT64 ui64OutBuffer;
+       } u;
+       IMG_SID hStream;
+       IMG_BOOL bReadInitBuffer;
+       IMG_UINT32 ui32OutBufferSize;
+} DBG_IN_READ, *PDBG_IN_READ;
+
+typedef struct _DBG_IN_OVERRIDEMODE_
+{
+       IMG_SID hStream;
+       IMG_UINT32 ui32Mode;
+} DBG_IN_OVERRIDEMODE, *PDBG_IN_OVERRIDEMODE;
+
+typedef struct _DBG_IN_ISCAPTUREFRAME_
+{
+       IMG_SID hStream;
+       IMG_BOOL bCheckPreviousFrame;
+} DBG_IN_ISCAPTUREFRAME, *PDBG_IN_ISCAPTUREFRAME;
+
+typedef struct _DBG_IN_SETMARKER_
+{
+       IMG_SID hStream;
+       IMG_UINT32 ui32Marker;
+} DBG_IN_SETMARKER, *PDBG_IN_SETMARKER;
+
+typedef struct _DBG_IN_WRITE_LF_
+{
+       union
+       {
+               IMG_UINT8 *pui8InBuffer;
+               IMG_UINT64 ui64InBuffer;
+       } u;
+       IMG_UINT32 ui32Flags;
+       IMG_SID    hStream;
+       IMG_UINT32 ui32Level;
+       IMG_UINT32 ui32BufferSize;
+} DBG_IN_WRITE_LF, *PDBG_IN_WRITE_LF;
+
+#define WRITELF_FLAGS_RESETBUF         0x00000001UL
+
+typedef struct _DBG_STREAM_CONTROL_
+{
+       IMG_BOOL   bInitPhaseComplete;
+       IMG_UINT32 ui32Flags;
+
+       IMG_UINT32 ui32CapMode;
+       IMG_UINT32 ui32OutMode;
+       IMG_UINT32 ui32DebugLevel;
+       IMG_UINT32 ui32DefaultMode;
+       IMG_UINT32 ui32Start;
+       IMG_UINT32 ui32End;
+       IMG_UINT32 ui32Current;
+       IMG_UINT32 ui32SampleRate;
+       IMG_UINT32 ui32Reserved;
+} DBG_STREAM_CONTROL, *PDBG_STREAM_CONTROL;
+typedef struct _DBG_STREAM_
+{
+       struct _DBG_STREAM_ *psNext;
+       struct _DBG_STREAM_ *psInitStream;
+       DBG_STREAM_CONTROL *psCtrl;
+       IMG_BOOL   bCircularAllowed;
+       IMG_PVOID  pvBase;
+       IMG_UINT32 ui32Size;
+       IMG_UINT32 ui32RPtr;
+       IMG_UINT32 ui32WPtr;
+       IMG_UINT32 ui32DataWritten;
+       IMG_UINT32 ui32Marker;
+       IMG_UINT32 ui32InitPhaseWOff;
+
+       IMG_CHAR szName[30];            
+} DBG_STREAM,*PDBG_STREAM;
+
+typedef struct _DBGKM_CONNECT_NOTIFIER_
+{
+       IMG_VOID (IMG_CALLCONV *pfnConnectNotifier)             (IMG_VOID);
+} DBGKM_CONNECT_NOTIFIER, *PDBGKM_CONNECT_NOTIFIER;
+
+typedef struct _DBGKM_SERVICE_TABLE_
+{
+       IMG_UINT32 ui32Size;
+       IMG_VOID *      (IMG_CALLCONV *pfnCreateStream)                 (IMG_CHAR * pszName,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32OutMode,IMG_UINT32 ui32Flags,IMG_UINT32 ui32Pages);
+       IMG_VOID        (IMG_CALLCONV *pfnDestroyStream)                (PDBG_STREAM psStream);
+       IMG_VOID *      (IMG_CALLCONV *pfnFindStream)                   (IMG_CHAR * pszName, IMG_BOOL bResetInitBuffer);
+       IMG_UINT32      (IMG_CALLCONV *pfnWriteString)                  (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+       IMG_UINT32      (IMG_CALLCONV *pfnReadString)                   (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+       IMG_UINT32      (IMG_CALLCONV *pfnWriteBIN)                             (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+       IMG_UINT32      (IMG_CALLCONV *pfnReadBIN)                              (PDBG_STREAM psStream,IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+       IMG_VOID        (IMG_CALLCONV *pfnSetCaptureMode)               (PDBG_STREAM psStream,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+       IMG_VOID        (IMG_CALLCONV *pfnSetOutputMode)                (PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+       IMG_VOID        (IMG_CALLCONV *pfnSetDebugLevel)                (PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+       IMG_VOID        (IMG_CALLCONV *pfnSetFrame)                             (PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+       IMG_UINT32      (IMG_CALLCONV *pfnGetFrame)                             (PDBG_STREAM psStream);
+       IMG_VOID        (IMG_CALLCONV *pfnOverrideMode)                 (PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+       IMG_VOID        (IMG_CALLCONV *pfnDefaultMode)                  (PDBG_STREAM psStream);
+       IMG_UINT32      (IMG_CALLCONV *pfnDBGDrivWrite2)                (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+       IMG_UINT32      (IMG_CALLCONV *pfnWriteStringCM)                (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+       IMG_UINT32      (IMG_CALLCONV *pfnWriteBINCM)                   (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+       IMG_VOID        (IMG_CALLCONV *pfnSetMarker)                    (PDBG_STREAM psStream,IMG_UINT32 ui32Marker);
+       IMG_UINT32      (IMG_CALLCONV *pfnGetMarker)                    (PDBG_STREAM psStream);
+       IMG_VOID        (IMG_CALLCONV *pfnStartInitPhase)               (PDBG_STREAM psStream);
+       IMG_VOID        (IMG_CALLCONV *pfnStopInitPhase)                (PDBG_STREAM psStream);
+       IMG_BOOL        (IMG_CALLCONV *pfnIsCaptureFrame)               (PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+       IMG_UINT32      (IMG_CALLCONV *pfnWriteLF)                              (PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+       IMG_UINT32      (IMG_CALLCONV *pfnReadLF)                               (PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+       IMG_UINT32      (IMG_CALLCONV *pfnGetStreamOffset)              (PDBG_STREAM psStream);
+       IMG_VOID        (IMG_CALLCONV *pfnSetStreamOffset)              (PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+       IMG_BOOL        (IMG_CALLCONV *pfnIsLastCaptureFrame)   (PDBG_STREAM psStream);
+       IMG_VOID        (IMG_CALLCONV *pfnWaitForEvent)                 (DBG_EVENT eEvent);
+       IMG_VOID        (IMG_CALLCONV *pfnSetConnectNotifier)   (DBGKM_CONNECT_NOTIFIER fn_notifier);
+       IMG_UINT32      (IMG_CALLCONV *pfnWritePersist)                 (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+
+
+#endif
diff --git a/drivers/staging/mrst/pvr/include4/img_defs.h b/drivers/staging/mrst/pvr/include4/img_defs.h
new file mode 100644 (file)
index 0000000..bcc2a84
--- /dev/null
@@ -0,0 +1,118 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include "img_types.h"
+
+typedef                enum    img_tag_TriStateSwitch
+{
+       IMG_ON          =       0x00,
+       IMG_OFF,
+       IMG_IGNORE
+
+} img_TriStateSwitch, * img_pTriStateSwitch;
+
+#define                IMG_SUCCESS                             0
+
+#define                IMG_NO_REG                              1
+
+#if defined (NO_INLINE_FUNCS)
+       #define INLINE
+       #define FORCE_INLINE
+#else
+#if defined (__cplusplus)
+       #define INLINE                                  inline
+       #define FORCE_INLINE                    inline
+#else
+#if    !defined(INLINE)
+       #define INLINE                                  __inline
+#endif
+       #define FORCE_INLINE                    static __inline
+#endif
+#endif
+
+
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define        PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if defined(UNICODE)
+typedef unsigned short         TCHAR, *PTCHAR, *PTSTR;
+#else
+typedef char                           TCHAR, *PTCHAR, *PTSTR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+
+                       #if defined(__linux__) || defined(__METAG)
+
+                               #define IMG_CALLCONV
+                               #define IMG_INTERNAL    __attribute__ ((visibility ("hidden")))
+                               #define IMG_EXPORT      __attribute__((visibility("default")))
+                               #define IMG_IMPORT
+                               #define IMG_RESTRICT    __restrict__
+
+                       #else
+                                       #error("define an OS")
+                       #endif
+
+#ifndef IMG_ABORT
+       #define IMG_ABORT()     abort()
+#endif
+
+#ifndef IMG_MALLOC
+       #define IMG_MALLOC(A)           malloc  (A)
+#endif
+
+#ifndef IMG_FREE
+       #define IMG_FREE(A)                     free    (A)
+#endif
+
+#define IMG_CONST const
+
+#if defined(__GNUC__)
+#define IMG_FORMAT_PRINTF(x,y)         __attribute__((format(printf,x,y)))
+#else
+#define IMG_FORMAT_PRINTF(x,y)
+#endif
+
+#if defined (_WIN64)
+#define IMG_UNDEF      (~0ULL)
+#else
+#define IMG_UNDEF      (~0UL)
+#endif
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/include4/img_types.h b/drivers/staging/mrst/pvr/include4/img_types.h
new file mode 100644 (file)
index 0000000..f119048
--- /dev/null
@@ -0,0 +1,143 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_TYPES_H__
+#define __IMG_TYPES_H__
+
+#include <drm/drm.h>
+
+#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
+#define IMG_ADDRSPACE_CPUVADDR_BITS            32
+#endif
+
+#if !defined(IMG_ADDRSPACE_PHYSADDR_BITS)
+#define IMG_ADDRSPACE_PHYSADDR_BITS            32
+#endif
+
+typedef uint32_t       IMG_UINT,       *IMG_PUINT;
+typedef int32_t                IMG_INT,        *IMG_PINT;
+
+typedef uint8_t                IMG_UINT8,      *IMG_PUINT8;
+typedef uint8_t                IMG_BYTE,       *IMG_PBYTE;
+typedef int8_t         IMG_INT8,       *IMG_PINT8;
+typedef char           IMG_CHAR,       *IMG_PCHAR;
+
+typedef uint16_t       IMG_UINT16,     *IMG_PUINT16;
+typedef int16_t                IMG_INT16,      *IMG_PINT16;
+
+
+#if !defined(IMG_UINT32_IS_ULONG)
+typedef uint32_t       IMG_UINT32,     *IMG_PUINT32;
+typedef int32_t                IMG_INT32,      *IMG_PINT32;
+#else
+typedef uint32_t       IMG_UINT32,     *IMG_PUINT32;
+typedef int32_t                IMG_INT32,      *IMG_PINT32;
+#endif
+
+
+#if !defined(IMG_UINT32_MAX)
+       #define IMG_UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+       #if (defined(LINUX) || defined(__METAG))
+#if !defined(USE_CODE)
+               typedef unsigned long long              IMG_UINT64,     *IMG_PUINT64;
+               typedef long long                               IMG_INT64,      *IMG_PINT64;
+#endif
+       #else
+
+               #error("define an OS")
+
+       #endif
+
+#if !(defined(LINUX) && defined (__KERNEL__))
+typedef float                  IMG_FLOAT,      *IMG_PFLOAT;
+typedef double                 IMG_DOUBLE, *IMG_PDOUBLE;
+#endif
+
+typedef        enum tag_img_bool
+{
+       IMG_FALSE               = 0,
+       IMG_TRUE                = 1,
+       IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+
+typedef void            IMG_VOID,      *IMG_PVOID;
+
+typedef IMG_INT32       IMG_RESULT;
+
+#if defined(_WIN64)
+typedef unsigned __int64 IMG_UINTPTR_T;
+#else
+typedef unsigned int     IMG_UINTPTR_T;
+#endif
+
+typedef IMG_PVOID       IMG_HANDLE;
+
+typedef void**          IMG_HVOID,     * IMG_PHVOID;
+
+typedef IMG_UINT32             IMG_SIZE_T;
+
+#define IMG_NULL        0
+
+typedef IMG_UINT32      IMG_SID;
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+typedef struct _IMG_DEV_VIRTADDR
+{
+
+       IMG_UINT32 uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var)         (IMG_UINT32)(var)
+
+} IMG_DEV_VIRTADDR;
+
+typedef struct _IMG_CPU_PHYADDR
+{
+
+       IMG_UINTPTR_T uiAddr;
+} IMG_CPU_PHYADDR;
+
+typedef struct _IMG_DEV_PHYADDR
+{
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+
+       IMG_UINTPTR_T uiAddr;
+#else
+       IMG_UINT32 uiAddr;
+       IMG_UINT32 uiHighAddr;
+#endif
+} IMG_DEV_PHYADDR;
+
+typedef struct _IMG_SYS_PHYADDR
+{
+
+       IMG_UINTPTR_T uiAddr;
+} IMG_SYS_PHYADDR;
+
+#include "img_defs.h"
+
+#endif
diff --git a/drivers/staging/mrst/pvr/include4/ioctldef.h b/drivers/staging/mrst/pvr/include4/ioctldef.h
new file mode 100644 (file)
index 0000000..cc69629
--- /dev/null
@@ -0,0 +1,98 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __IOCTLDEF_H__
+#define __IOCTLDEF_H__
+
+#define MAKEIOCTLINDEX(i)      (((i) >> 2) & 0xFFF)
+
+#ifndef CTL_CODE
+
+#define DEVICE_TYPE ULONG
+
+#define FILE_DEVICE_BEEP                0x00000001
+#define FILE_DEVICE_CD_ROM              0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM  0x00000003
+#define FILE_DEVICE_CONTROLLER          0x00000004
+#define FILE_DEVICE_DATALINK            0x00000005
+#define FILE_DEVICE_DFS                 0x00000006
+#define FILE_DEVICE_DISK                0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM    0x00000008
+#define FILE_DEVICE_FILE_SYSTEM         0x00000009
+#define FILE_DEVICE_INPORT_PORT         0x0000000a
+#define FILE_DEVICE_KEYBOARD            0x0000000b
+#define FILE_DEVICE_MAILSLOT            0x0000000c
+#define FILE_DEVICE_MIDI_IN             0x0000000d
+#define FILE_DEVICE_MIDI_OUT            0x0000000e
+#define FILE_DEVICE_MOUSE               0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER  0x00000010
+#define FILE_DEVICE_NAMED_PIPE          0x00000011
+#define FILE_DEVICE_NETWORK             0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER     0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL                0x00000015
+#define FILE_DEVICE_PARALLEL_PORT       0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD    0x00000017
+#define FILE_DEVICE_PRINTER             0x00000018
+#define FILE_DEVICE_SCANNER             0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT   0x0000001a
+#define FILE_DEVICE_SERIAL_PORT         0x0000001b
+#define FILE_DEVICE_SCREEN              0x0000001c
+#define FILE_DEVICE_SOUND               0x0000001d
+#define FILE_DEVICE_STREAMS             0x0000001e
+#define FILE_DEVICE_TAPE                0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM    0x00000020
+#define FILE_DEVICE_TRANSPORT           0x00000021
+#define FILE_DEVICE_UNKNOWN             0x00000022
+#define FILE_DEVICE_VIDEO               0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK        0x00000024
+#define FILE_DEVICE_WAVE_IN             0x00000025
+#define FILE_DEVICE_WAVE_OUT            0x00000026
+#define FILE_DEVICE_8042_PORT           0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR  0x00000028
+#define FILE_DEVICE_BATTERY             0x00000029
+#define FILE_DEVICE_BUS_EXTENDER        0x0000002a
+#define FILE_DEVICE_MODEM               0x0000002b
+#define FILE_DEVICE_VDM                 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE        0x0000002d
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
+    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define METHOD_BUFFERED                 0
+#define METHOD_IN_DIRECT                1
+#define METHOD_OUT_DIRECT               2
+#define METHOD_NEITHER                  3
+
+#define FILE_ANY_ACCESS                 0
+#define FILE_READ_ACCESS          ( 0x0001 )
+#define FILE_WRITE_ACCESS         ( 0x0002 )
+
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/include4/pdumpdefs.h b/drivers/staging/mrst/pvr/include4/pdumpdefs.h
new file mode 100644 (file)
index 0000000..3a2e4c1
--- /dev/null
@@ -0,0 +1,99 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__PDUMPDEFS_H__)
+#define __PDUMPDEFS_H__
+
+typedef enum _PDUMP_PIXEL_FORMAT_
+{
+       PVRSRV_PDUMP_PIXEL_FORMAT_UNSUPPORTED = 0,
+       PVRSRV_PDUMP_PIXEL_FORMAT_RGB8 = 1,
+       PVRSRV_PDUMP_PIXEL_FORMAT_RGB332 = 2,
+       PVRSRV_PDUMP_PIXEL_FORMAT_KRGB555 = 3,
+       PVRSRV_PDUMP_PIXEL_FORMAT_RGB565 = 4,
+       PVRSRV_PDUMP_PIXEL_FORMAT_ARGB4444 = 5,
+       PVRSRV_PDUMP_PIXEL_FORMAT_ARGB1555 = 6,
+       PVRSRV_PDUMP_PIXEL_FORMAT_RGB888 = 7,
+       PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8888 = 8,
+       PVRSRV_PDUMP_PIXEL_FORMAT_YUV8 = 9,
+       PVRSRV_PDUMP_PIXEL_FORMAT_AYUV4444 = 10,
+       PVRSRV_PDUMP_PIXEL_FORMAT_VY0UY1_8888 = 11,
+       PVRSRV_PDUMP_PIXEL_FORMAT_UY0VY1_8888 = 12,
+       PVRSRV_PDUMP_PIXEL_FORMAT_Y0UY1V_8888 = 13,
+       PVRSRV_PDUMP_PIXEL_FORMAT_Y0VY1U_8888 = 14,
+       PVRSRV_PDUMP_PIXEL_FORMAT_YUV888 = 15,
+       PVRSRV_PDUMP_PIXEL_FORMAT_UYVY10101010 = 16,
+       PVRSRV_PDUMP_PIXEL_FORMAT_VYAUYA8888 = 17,
+       PVRSRV_PDUMP_PIXEL_FORMAT_AYUV8888 = 18,
+       PVRSRV_PDUMP_PIXEL_FORMAT_AYUV2101010 = 19,
+       PVRSRV_PDUMP_PIXEL_FORMAT_YUV101010 = 20,
+       PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y8 = 21,
+       PVRSRV_PDUMP_PIXEL_FORMAT_YUV_IMC2 = 22,
+       PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12 = 23,
+       PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL8 = 24,
+       PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL12 = 25,
+       PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV8 = 26,
+       PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8 = 27,
+       PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y10 = 28,
+       PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV10 = 29,
+       PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV10 = 30,
+       PVRSRV_PDUMP_PIXEL_FORMAT_ABGR8888 = 31,
+       PVRSRV_PDUMP_PIXEL_FORMAT_BGRA8888 = 32,
+       PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8332 = 33,
+       PVRSRV_PDUMP_PIXEL_FORMAT_RGB555 = 34,
+       PVRSRV_PDUMP_PIXEL_FORMAT_F16 = 35,
+       PVRSRV_PDUMP_PIXEL_FORMAT_F32 = 36,
+       PVRSRV_PDUMP_PIXEL_FORMAT_L16 = 37,
+       PVRSRV_PDUMP_PIXEL_FORMAT_L32 = 38,
+
+       PVRSRV_PDUMP_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PDUMP_PIXEL_FORMAT;
+
+typedef enum _PDUMP_MEM_FORMAT_
+{
+       PVRSRV_PDUMP_MEM_FORMAT_STRIDE = 0,
+       PVRSRV_PDUMP_MEM_FORMAT_RESERVED = 1,
+       PVRSRV_PDUMP_MEM_FORMAT_TILED = 8,
+       PVRSRV_PDUMP_MEM_FORMAT_TWIDDLED = 9,
+       PVRSRV_PDUMP_MEM_FORMAT_HYBRID = 10,
+
+       PVRSRV_PDUMP_MEM_FORMAT_FORCE_I32 = 0x7fffffff
+} PDUMP_MEM_FORMAT;
+
+typedef enum _PDUMP_POLL_OPERATOR
+{
+       PDUMP_POLL_OPERATOR_EQUAL = 0,
+       PDUMP_POLL_OPERATOR_LESS = 1,
+       PDUMP_POLL_OPERATOR_LESSEQUAL = 2,
+       PDUMP_POLL_OPERATOR_GREATER = 3,
+       PDUMP_POLL_OPERATOR_GREATEREQUAL = 4,
+       PDUMP_POLL_OPERATOR_NOTEQUAL = 5,
+} PDUMP_POLL_OPERATOR;
+
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/include4/pvr_debug.h b/drivers/staging/mrst/pvr/include4/pvr_debug.h
new file mode 100644 (file)
index 0000000..09c949c
--- /dev/null
@@ -0,0 +1,133 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_DEBUG_H__
+#define __PVR_DEBUG_H__
+
+
+#include "img_types.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define PVR_MAX_DEBUG_MESSAGE_LEN      (512)
+
+#define DBGPRIV_FATAL          0x01UL
+#define DBGPRIV_ERROR          0x02UL
+#define DBGPRIV_WARNING                0x04UL
+#define DBGPRIV_MESSAGE                0x08UL
+#define DBGPRIV_VERBOSE                0x10UL
+#define DBGPRIV_CALLTRACE      0x20UL
+#define DBGPRIV_ALLOC          0x40UL
+
+#define DBGPRIV_DBGDRV_MESSAGE 0x1000UL
+
+#define DBGPRIV_ALLLEVELS      (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING | DBGPRIV_MESSAGE | DBGPRIV_VERBOSE)
+
+
+
+#define PVR_DBG_FATAL          DBGPRIV_FATAL,__FILE__, __LINE__
+#define PVR_DBG_ERROR          DBGPRIV_ERROR,__FILE__, __LINE__
+#define PVR_DBG_WARNING                DBGPRIV_WARNING,__FILE__, __LINE__
+#define PVR_DBG_MESSAGE                DBGPRIV_MESSAGE,__FILE__, __LINE__
+#define PVR_DBG_VERBOSE                DBGPRIV_VERBOSE,__FILE__, __LINE__
+#define PVR_DBG_CALLTRACE      DBGPRIV_CALLTRACE,__FILE__, __LINE__
+#define PVR_DBG_ALLOC          DBGPRIV_ALLOC,__FILE__, __LINE__
+
+#define PVR_DBGDRIV_MESSAGE            DBGPRIV_DBGDRV_MESSAGE, "", 0
+
+#if !defined(PVRSRV_NEED_PVR_ASSERT) && defined(DEBUG)
+#define PVRSRV_NEED_PVR_ASSERT
+#endif
+
+#if defined(PVRSRV_NEED_PVR_ASSERT) && !defined(PVRSRV_NEED_PVR_DPF)
+#define PVRSRV_NEED_PVR_DPF
+#endif
+
+#if !defined(PVRSRV_NEED_PVR_TRACE) && (defined(DEBUG) || defined(TIMING))
+#define PVRSRV_NEED_PVR_TRACE
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+       #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
+                                                                                                          IMG_UINT32 ui32Line);
+
+                       #if defined(PVR_DBG_BREAK_ASSERT_FAIL)
+                               #define PVR_DBG_BREAK   PVRSRVDebugAssertFail("PVR_DBG_BREAK", 0)
+                       #else
+                               #define PVR_DBG_BREAK
+                       #endif
+
+#else
+
+       #define PVR_ASSERT(EXPR)
+       #define PVR_DBG_BREAK
+
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+       #define PVR_DPF(X)              PVRSRVDebugPrintf X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+                                                                                                  const IMG_CHAR *pszFileName,
+                                                                                                  IMG_UINT32 ui32Line,
+                                                                                                  const IMG_CHAR *pszFormat,
+                                                                                                  ...) IMG_FORMAT_PRINTF(4, 5);
+
+#else
+
+       #define PVR_DPF(X)
+
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+       #define PVR_TRACE(X)    PVRSRVTrace X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
+       IMG_FORMAT_PRINTF(1, 2);
+
+#else
+
+       #define PVR_TRACE(X)
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/include4/pvrmodule.h b/drivers/staging/mrst/pvr/include4/pvrmodule.h
new file mode 100644 (file)
index 0000000..5f77d1c
--- /dev/null
@@ -0,0 +1,31 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef        _PVRMODULE_H_
+#define        _PVRMODULE_H_
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/staging/mrst/pvr/include4/pvrversion.h b/drivers/staging/mrst/pvr/include4/pvrversion.h
new file mode 100644 (file)
index 0000000..ad42d39
--- /dev/null
@@ -0,0 +1,38 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 6
+#define PVRVERSION_BRANCH 16
+#define PVRVERSION_BUILD 4043
+#define PVRVERSION_STRING "1.6.16.4043"
+#define PVRVERSION_FILE "eurasiacon.pj"
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/include4/regpaths.h b/drivers/staging/mrst/pvr/include4/regpaths.h
new file mode 100644 (file)
index 0000000..8dac213
--- /dev/null
@@ -0,0 +1,43 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __REGPATHS_H__
+#define __REGPATHS_H__
+
+#define POWERVR_REG_ROOT                               "Drivers\\Display\\PowerVR"
+#define POWERVR_CHIP_KEY                               "\\SGX1\\"
+
+#define POWERVR_EURASIA_KEY                            "PowerVREurasia\\"
+
+#define POWERVR_SERVICES_KEY                   "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\PowerVR\\"
+
+#define PVRSRV_REGISTRY_ROOT                   POWERVR_EURASIA_KEY "HWSettings\\PVRSRVKM"
+
+
+#define MAX_REG_STRING_SIZE 128
+
+
+#endif
diff --git a/drivers/staging/mrst/pvr/include4/services.h b/drivers/staging/mrst/pvr/include4/services.h
new file mode 100644 (file)
index 0000000..edb6d11
--- /dev/null
@@ -0,0 +1,995 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __SERVICES_H__
+#define __SERVICES_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "pdumpdefs.h"
+
+
+#define PVRSRV_4K_PAGE_SIZE            4096UL
+
+#define PVRSRV_MAX_CMD_SIZE            1024
+
+#define PVRSRV_MAX_DEVICES             16
+
+#define EVENTOBJNAME_MAXLENGTH (50)
+
+#define PVRSRV_MEM_READ                                                (1U<<0)
+#define PVRSRV_MEM_WRITE                                       (1U<<1)
+#define PVRSRV_MEM_CACHE_CONSISTENT                    (1U<<2)
+#define PVRSRV_MEM_NO_SYNCOBJ                          (1U<<3)
+#define PVRSRV_MEM_INTERLEAVED                         (1U<<4)
+#define PVRSRV_MEM_DUMMY                                       (1U<<5)
+#define PVRSRV_MEM_EDM_PROTECT                         (1U<<6)
+#define PVRSRV_MEM_ZERO                                                (1U<<7)
+#define PVRSRV_MEM_USER_SUPPLIED_DEVVADDR      (1U<<8)
+#define PVRSRV_MEM_RAM_BACKED_ALLOCATION       (1U<<9)
+#define PVRSRV_MEM_NO_RESMAN                           (1U<<10)
+#define PVRSRV_MEM_EXPORTED                                    (1U<<11)
+
+
+#define PVRSRV_HAP_CACHED                                      (1U<<12)
+#define PVRSRV_HAP_UNCACHED                                    (1U<<13)
+#define PVRSRV_HAP_WRITECOMBINE                                (1U<<14)
+#define PVRSRV_HAP_CACHETYPE_MASK                      (PVRSRV_HAP_CACHED|PVRSRV_HAP_UNCACHED|PVRSRV_HAP_WRITECOMBINE)
+#define PVRSRV_HAP_KERNEL_ONLY                         (1U<<15)
+#define PVRSRV_HAP_SINGLE_PROCESS                      (1U<<16)
+#define PVRSRV_HAP_MULTI_PROCESS                       (1U<<17)
+#define PVRSRV_HAP_FROM_EXISTING_PROCESS       (1U<<18)
+#define PVRSRV_HAP_NO_CPU_VIRTUAL                      (1U<<19)
+#define PVRSRV_HAP_MAPTYPE_MASK                                (PVRSRV_HAP_KERNEL_ONLY \
+                                            |PVRSRV_HAP_SINGLE_PROCESS \
+                                            |PVRSRV_HAP_MULTI_PROCESS \
+                                            |PVRSRV_HAP_FROM_EXISTING_PROCESS \
+                                            |PVRSRV_HAP_NO_CPU_VIRTUAL)
+
+#define PVRSRV_MEM_CACHED                                      PVRSRV_HAP_CACHED
+#define PVRSRV_MEM_UNCACHED                                    PVRSRV_HAP_UNCACHED
+#define PVRSRV_MEM_WRITECOMBINE                                PVRSRV_HAP_WRITECOMBINE
+
+#define PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT    (24)
+
+#define PVRSRV_MAP_NOUSERVIRTUAL            (1UL<<27)
+
+#define PVRSRV_NO_CONTEXT_LOSS                                 0
+#define PVRSRV_SEVERE_LOSS_OF_CONTEXT                  1
+#define PVRSRV_PRE_STATE_CHANGE_MASK                   0x80
+
+
+#define PVRSRV_DEFAULT_DEV_COOKIE                      (1)
+
+
+#define PVRSRV_MISC_INFO_TIMER_PRESENT                         (1U<<0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT                     (1U<<1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT                      (1U<<2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT     (1U<<3)
+#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT                    (1U<<4)
+#define PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT                    (1U<<5)
+#define PVRSRV_MISC_INFO_FREEMEM_PRESENT                       (1U<<6)
+
+#define PVRSRV_MISC_INFO_RESET_PRESENT                         (1U<<31)
+
+#define PVRSRV_PDUMP_MAX_FILENAME_SIZE                 20
+#define PVRSRV_PDUMP_MAX_COMMENT_SIZE                  200
+
+
+#define PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT              0x00000001
+
+#define PVRSRV_MAPEXTMEMORY_FLAGS_ALTERNATEVA                  0x00000001
+#define PVRSRV_MAPEXTMEMORY_FLAGS_PHYSCONTIG                   0x00000002
+
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC                      0x00000001
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC                      0x00000002
+
+#define SRV_FLAGS_PERSIST              0x1
+#define SRV_FLAGS_PDUMP_ACTIVE 0x2
+
+#define PVRSRV_PDUMP_FLAGS_CONTINUOUS          0x1
+
+
+typedef enum _PVRSRV_DEVICE_TYPE_
+{
+       PVRSRV_DEVICE_TYPE_UNKNOWN                      = 0 ,
+       PVRSRV_DEVICE_TYPE_MBX1                         = 1 ,
+       PVRSRV_DEVICE_TYPE_MBX1_LITE            = 2 ,
+
+       PVRSRV_DEVICE_TYPE_M24VA                        = 3,
+       PVRSRV_DEVICE_TYPE_MVDA2                        = 4,
+       PVRSRV_DEVICE_TYPE_MVED1                        = 5,
+       PVRSRV_DEVICE_TYPE_MSVDX                        = 6,
+
+       PVRSRV_DEVICE_TYPE_SGX                          = 7,
+
+       PVRSRV_DEVICE_TYPE_VGX                          = 8,
+
+       PVRSRV_DEVICE_TYPE_TOPAZ                        = 9,
+
+       PVRSRV_DEVICE_TYPE_EXT                          = 10,
+
+       PVRSRV_DEVICE_TYPE_LAST                         = 10,
+
+       PVRSRV_DEVICE_TYPE_FORCE_I32            = 0x7fffffff
+
+} PVRSRV_DEVICE_TYPE;
+
+#define HEAP_ID( _dev_ , _dev_heap_idx_ )      (  ((_dev_)<<24) | ((_dev_heap_idx_)&((1<<24)-1))  )
+#define HEAP_IDX( _heap_id_ )                          ( (_heap_id_)&((1<<24) - 1 ) )
+#define HEAP_DEV( _heap_id_ )                          ( (_heap_id_)>>24 )
+
+#define PVRSRV_UNDEFINED_HEAP_ID                       (~0LU)
+
+typedef enum
+{
+       IMG_EGL                         = 0x00000001,
+       IMG_OPENGLES1           = 0x00000002,
+       IMG_OPENGLES2           = 0x00000003,
+       IMG_D3DM                        = 0x00000004,
+       IMG_SRV_UM                      = 0x00000005,
+       IMG_OPENVG                      = 0x00000006,
+       IMG_SRVCLIENT           = 0x00000007,
+       IMG_VISTAKMD            = 0x00000008,
+       IMG_VISTA3DNODE         = 0x00000009,
+       IMG_VISTAMVIDEONODE     = 0x0000000A,
+       IMG_VISTAVPBNODE        = 0x0000000B,
+       IMG_OPENGL                      = 0x0000000C,
+       IMG_D3D                         = 0x0000000D,
+#if defined(SUPPORT_GRAPHICS_HAL)
+       IMG_GRAPHICS_HAL        = 0x0000000E
+#endif
+
+} IMG_MODULE_ID;
+
+
+#define APPHINT_MAX_STRING_SIZE        256
+
+typedef enum
+{
+       IMG_STRING_TYPE         = 1,
+       IMG_FLOAT_TYPE          ,
+       IMG_UINT_TYPE           ,
+       IMG_INT_TYPE            ,
+       IMG_FLAG_TYPE
+}IMG_DATA_TYPE;
+
+
+typedef struct _PVRSRV_DEV_DATA_ *PPVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_DEVICE_IDENTIFIER_
+{
+       PVRSRV_DEVICE_TYPE              eDeviceType;
+       PVRSRV_DEVICE_CLASS             eDeviceClass;
+       IMG_UINT32                              ui32DeviceIndex;
+       IMG_CHAR                                *pszPDumpDevName;       
+       IMG_CHAR                                *pszPDumpRegName;       
+
+} PVRSRV_DEVICE_IDENTIFIER;
+
+
+typedef struct _PVRSRV_CLIENT_DEV_DATA_
+{
+       IMG_UINT32              ui32NumDevices;                         
+       PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES];           
+       PVRSRV_ERROR    (*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);        
+       PVRSRV_ERROR    (*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);         
+
+} PVRSRV_CLIENT_DEV_DATA;
+
+
+typedef struct _PVRSRV_CONNECTION_
+{
+       IMG_HANDLE hServices;                                   
+       IMG_UINTPTR_T ui32ProcessID;                    
+       PVRSRV_CLIENT_DEV_DATA  sClientDevData; 
+       IMG_UINT32 ui32SrvFlags;                                
+}PVRSRV_CONNECTION;
+
+
+typedef struct _PVRSRV_DEV_DATA_
+{
+       IMG_CONST PVRSRV_CONNECTION      *psConnection; 
+       IMG_HANDLE                      hDevCookie;                             
+
+} PVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_MEMUPDATE_
+{
+       IMG_UINTPTR_T           ui32UpdateAddr;         
+       IMG_UINT32                      ui32UpdateVal;          
+} PVRSRV_MEMUPDATE;
+
+typedef struct _PVRSRV_HWREG_
+{
+       IMG_UINT32                      ui32RegAddr;
+       IMG_UINT32                      ui32RegVal;
+} PVRSRV_HWREG;
+
+typedef struct _PVRSRV_MEMBLK_
+{
+       IMG_DEV_VIRTADDR        sDevVirtAddr;
+       IMG_HANDLE                      hOSMemHandle;
+       IMG_HANDLE                      hOSWrapMem;
+       IMG_HANDLE                      hBuffer;
+       IMG_HANDLE                      hResItem;
+       IMG_SYS_PHYADDR         *psIntSysPAddr;
+
+} PVRSRV_MEMBLK;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_ *PPVRSRV_KERNEL_MEM_INFO;
+
+typedef struct _PVRSRV_CLIENT_MEM_INFO_
+{
+
+       IMG_PVOID                               pvLinAddr;
+
+
+       IMG_PVOID                               pvLinAddrKM;
+
+
+       IMG_DEV_VIRTADDR                sDevVAddr;
+
+
+
+
+
+
+       IMG_CPU_PHYADDR                 sCpuPAddr;
+
+
+       IMG_UINT32                              ui32Flags;
+
+
+
+
+       IMG_UINT32                              ui32ClientFlags;
+
+
+       IMG_SIZE_T                              ui32AllocSize;
+
+
+
+       struct _PVRSRV_CLIENT_SYNC_INFO_        *psClientSyncInfo;
+
+
+       IMG_HANDLE                                                      hMappingInfo;
+
+
+       IMG_HANDLE                                                      hKernelMemInfo;
+
+
+       IMG_HANDLE                                                      hResItem;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+       #if !defined(USE_CODE)
+
+       IMG_UINT64                                                      ui64Stamp;
+       #else
+       IMG_UINT32                                                      dummy1;
+       IMG_UINT32                                                      dummy2;
+       #endif
+#endif
+
+
+
+
+       struct _PVRSRV_CLIENT_MEM_INFO_         *psNext;
+
+} PVRSRV_CLIENT_MEM_INFO, *PPVRSRV_CLIENT_MEM_INFO;
+
+
+#define PVRSRV_MAX_CLIENT_HEAPS (32)
+typedef struct _PVRSRV_HEAP_INFO_
+{
+       IMG_UINT32                      ui32HeapID;
+       IMG_HANDLE                      hDevMemHeap;
+       IMG_DEV_VIRTADDR        sDevVAddrBase;
+       IMG_UINT32                      ui32HeapByteSize;
+       IMG_UINT32                      ui32Attribs;
+       IMG_UINT32                      ui32XTileStride;
+}PVRSRV_HEAP_INFO;
+
+
+
+
+typedef struct _PVRSRV_EVENTOBJECT_
+{
+
+       IMG_CHAR        szName[EVENTOBJNAME_MAXLENGTH];
+
+       IMG_HANDLE      hOSEventKM;
+
+} PVRSRV_EVENTOBJECT;
+
+typedef enum
+{
+       PVRSRV_MISC_INFO_CPUCACHEOP_NONE = 0,
+       PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN,
+       PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH
+} PVRSRV_MISC_INFO_CPUCACHEOP_TYPE;
+
+typedef struct _PVRSRV_MISC_INFO_
+{
+       IMG_UINT32      ui32StateRequest;
+       IMG_UINT32      ui32StatePresent;
+
+
+       IMG_VOID        *pvSOCTimerRegisterKM;
+       IMG_VOID        *pvSOCTimerRegisterUM;
+       IMG_HANDLE      hSOCTimerRegisterOSMemHandle;
+       IMG_HANDLE      hSOCTimerRegisterMappingInfo;
+
+
+       IMG_VOID        *pvSOCClockGateRegs;
+       IMG_UINT32      ui32SOCClockGateRegsSize;
+
+
+       IMG_CHAR        *pszMemoryStr;
+       IMG_UINT32      ui32MemoryStrLen;
+
+
+       PVRSRV_EVENTOBJECT      sGlobalEventObject;
+       IMG_HANDLE                      hOSGlobalEvent;
+
+
+       IMG_UINT32      aui32DDKVersion[4];
+
+
+       struct
+       {
+               
+               IMG_BOOL bDeferOp;
+
+               
+               PVRSRV_MISC_INFO_CPUCACHEOP_TYPE eCacheOpType;
+
+               
+               union
+               {
+                       
+                       PVRSRV_CLIENT_MEM_INFO *psClientMemInfo;
+
+                       
+                       struct _PVRSRV_KERNEL_MEM_INFO_ *psKernelMemInfo;
+               } u;
+
+               
+               IMG_VOID *pvBaseVAddr;
+
+               
+               IMG_UINT32      ui32Length;
+       } sCacheOpCtl;
+} PVRSRV_MISC_INFO;
+
+
+typedef enum _PVRSRV_CLIENT_EVENT_
+{
+       PVRSRV_CLIENT_EVENT_HWTIMEOUT = 0,
+} PVRSRV_CLIENT_EVENT;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVClientEvent(IMG_CONST PVRSRV_CLIENT_EVENT eEvent,
+                                                                                       PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_PVOID pvData);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION **ppsConnection, IMG_UINT32 ui32SrvFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDisconnect(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevices(IMG_CONST PVRSRV_CONNECTION                   *psConnection,
+                                                                                                       IMG_UINT32                                      *puiNumDevices,
+                                                                                                       PVRSRV_DEVICE_IDENTIFIER        *puiDevIDs);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceData(IMG_CONST PVRSRV_CONNECTION  *psConnection,
+                                                                                                       IMG_UINT32                      uiDevIndex,
+                                                                                                       PVRSRV_DEV_DATA         *psDevData,
+                                                                                                       PVRSRV_DEVICE_TYPE      eDeviceType);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+#if 1
+IMG_IMPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+IMG_IMPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+
+IMG_IMPORT IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPollForValue ( const PVRSRV_CONNECTION *psConnection,
+                                                       IMG_HANDLE hOSEvent,
+                                                       volatile IMG_UINT32 *pui32LinMemAddr,
+                                                       IMG_UINT32 ui32Value,
+                                                       IMG_UINT32 ui32Mask,
+                                                       IMG_UINT32 ui32Waitus,
+                                                       IMG_UINT32 ui32Tries);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_HANDLE *phDevMemContext,
+                                                                                       IMG_UINT32 *pui32SharedHeapCount,
+                                                                                       PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_HANDLE                      hDevMemContext);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_HANDLE hDevMemContext,
+                                                                                       IMG_UINT32 *pui32SharedHeapCount,
+                                                                                       PVRSRV_HEAP_INFO *psHeapInfo);
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+       #define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+               (PVR_TRACE(("PVRSRVAllocDeviceMem(" #psDevData "," #hDevMemHeap "," #ui32Attribs "," #ui32Size "," #ui32Alignment "," #ppsMemInfo ")" \
+                       ": " logStr " (size = 0x%lx)", ui32Size)), \
+               PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo))
+#else
+       #define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+               PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem(IMG_CONST PVRSRV_DEV_DATA       *psDevData,
+                                                                       IMG_HANDLE              hDevMemHeap,
+                                                                       IMG_UINT32              ui32Attribs,
+                                                                       IMG_SIZE_T              ui32Size,
+                                                                       IMG_SIZE_T              ui32Alignment,
+                                                                       PVRSRV_CLIENT_MEM_INFO  **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMem(IMG_CONST PVRSRV_DEV_DATA        *psDevData,
+                                                               PVRSRV_CLIENT_MEM_INFO          *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem(IMG_CONST PVRSRV_DEV_DATA      *psDevData,
+                                                                                               PVRSRV_CLIENT_MEM_INFO          *psMemInfo,
+                                                                                               IMG_HANDLE                                      *phMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_HANDLE                      hDevMemHeap,
+                                                                                       IMG_DEV_VIRTADDR        *psDevVAddr,
+                                                                                       IMG_SIZE_T                      ui32Size,
+                                                                                       IMG_SIZE_T                      ui32Alignment,
+                                                                                       PVRSRV_CLIENT_MEM_INFO          **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                                       PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                       IMG_HANDLE hKernelMemInfo,
+                                                                       IMG_HANDLE hDstDevMemHeap,
+                                                                       PVRSRV_CLIENT_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                               PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapExtMemory (IMG_CONST PVRSRV_DEV_DATA        *psDevData,
+                                                                       PVRSRV_CLIENT_MEM_INFO          *psMemInfo,
+                                                                       IMG_SYS_PHYADDR                         *psSysPAddr,
+                                                                       IMG_UINT32                                      ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                       PVRSRV_CLIENT_MEM_INFO          *psMemInfo,
+                                                                       IMG_UINT32                                      ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemory(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                               IMG_HANDLE                              hDevMemContext,
+                                                                                               IMG_SIZE_T                              ui32ByteSize,
+                                                                                               IMG_SIZE_T                              ui32PageOffset,
+                                                                                               IMG_BOOL                                bPhysContig,
+                                                                                               IMG_SYS_PHYADDR                 *psSysPAddr,
+                                                                                               IMG_VOID                                *pvLinAddr,
+                                                                                               IMG_UINT32                              ui32Flags,
+                                                                                               PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                               PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+PVRSRV_ERROR PVRSRVChangeDeviceMemoryAttributes(IMG_CONST PVRSRV_DEV_DATA                      *psDevData,
+                                                                                               PVRSRV_CLIENT_MEM_INFO  *psClientMemInfo,
+                                                                                               IMG_UINT32                              ui32Attribs);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                               IMG_HANDLE hDevMemContext,
+                                                                               IMG_HANDLE hDeviceClassBuffer,
+                                                                               PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                               PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                         IMG_SYS_PHYADDR sSysPhysAddr,
+                                                                         IMG_UINT32 uiSizeInBytes,
+                                                                         IMG_PVOID *ppvUserAddr,
+                                                                         IMG_UINT32 *puiActualSize,
+                                                                         IMG_PVOID *ppvProcess);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                               IMG_PVOID pvUserAddr,
+                                                                               IMG_PVOID pvProcess);
+
+typedef enum _PVRSRV_SYNCVAL_MODE_
+{
+       PVRSRV_SYNCVAL_READ                             = IMG_TRUE,
+       PVRSRV_SYNCVAL_WRITE                    = IMG_FALSE,
+
+} PVRSRV_SYNCVAL_MODE, *PPVRSRV_SYNCVAL_MODE;
+
+typedef IMG_UINT32 PVRSRV_SYNCVAL;
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+       PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+       PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+       PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+       PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+       PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+       PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT PVRSRV_SYNCVAL PVRSRVGetPendingOpSyncVal(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+       PVRSRV_SYNCVAL_MODE eMode);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDeviceClass(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                                       PVRSRV_DEVICE_CLASS DeviceClass,
+                                                                                                       IMG_UINT32 *pui32DevCount,
+                                                                                                       IMG_UINT32 *pui32DevID);
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenDCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseDCDevice(IMG_CONST PVRSRV_CONNECTION      *psConnection, IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCFormats (IMG_HANDLE hDevice,
+                                                                                       IMG_UINT32              *pui32Count,
+                                                                                       DISPLAY_FORMAT  *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCDims (IMG_HANDLE hDevice,
+                                                                               IMG_UINT32              *pui32Count,
+                                                                               DISPLAY_FORMAT  *psFormat,
+                                                                               DISPLAY_DIMS    *psDims);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCSystemBuffer(IMG_HANDLE hDevice,
+                                                                               IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCInfo(IMG_HANDLE hDevice,
+                                                                               DISPLAY_INFO* psDisplayInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDCSwapChain (IMG_HANDLE                          hDevice,
+                                                                                                       IMG_UINT32                              ui32Flags,
+                                                                                                       DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+                                                                                                       DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+                                                                                                       IMG_UINT32                              ui32BufferCount,
+                                                                                                       IMG_UINT32                              ui32OEMFlags,
+                                                                                                       IMG_UINT32                              *pui32SwapChainID,
+                                                                                                       IMG_HANDLE                              *phSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDCSwapChain (IMG_HANDLE hDevice,
+                                                                                       IMG_HANDLE              hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstRect (IMG_HANDLE hDevice,
+                                                                               IMG_HANDLE      hSwapChain,
+                                                                               IMG_RECT        *psDstRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcRect (IMG_HANDLE hDevice,
+                                                                               IMG_HANDLE      hSwapChain,
+                                                                               IMG_RECT        *psSrcRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstColourKey (IMG_HANDLE hDevice,
+                                                                                       IMG_HANDLE      hSwapChain,
+                                                                                       IMG_UINT32      ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcColourKey (IMG_HANDLE hDevice,
+                                                                                       IMG_HANDLE      hSwapChain,
+                                                                                       IMG_UINT32      ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers(IMG_HANDLE hDevice,
+                                                                       IMG_HANDLE hSwapChain,
+                                                                       IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer (IMG_HANDLE hDevice,
+                                                                               IMG_HANDLE hBuffer,
+                                                                               IMG_UINT32 ui32ClipRectCount,
+                                                                               IMG_RECT *psClipRect,
+                                                                               IMG_UINT32 ui32SwapInterval,
+                                                                               IMG_HANDLE hPrivateTag);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCSystem (IMG_HANDLE hDevice,
+                                                                               IMG_HANDLE hSwapChain);
+
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenBCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseBCDevice(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                               IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBufferInfo(IMG_HANDLE hDevice,
+                                                                                               BUFFER_INFO     *psBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBuffer(IMG_HANDLE hDevice,
+                                                                                               IMG_UINT32 ui32BufferIndex,
+                                                                                               IMG_HANDLE *phBuffer);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpInit(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStartInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStopInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                 PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+                                                                                 IMG_UINT32 ui32Offset,
+                                                                                 IMG_UINT32 ui32Value,
+                                                                                 IMG_UINT32 ui32Mask,
+                                                                                 PDUMP_POLL_OPERATOR eOperator,
+                                                                                 IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSyncPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                 PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+                                                                                 IMG_BOOL bIsRead,
+                                                                                 IMG_UINT32 ui32Value,
+                                                                                 IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMem(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                       IMG_PVOID pvAltLinAddr,
+                                                                       PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+                                                                       IMG_UINT32 ui32Offset,
+                                                                       IMG_UINT32 ui32Bytes,
+                                                                       IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSync(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                               IMG_PVOID pvAltLinAddr,
+                                                                               PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+                                                                               IMG_UINT32 ui32Offset,
+                                                                               IMG_UINT32 ui32Bytes);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpReg(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                IMG_CHAR *pszRegRegion,
+                                                                                       IMG_UINT32 ui32RegAddr,
+                                                                                       IMG_UINT32 ui32RegValue,
+                                                                                       IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPolWithFlags(const PVRSRV_DEV_DATA *psDevData,
+                                                                                                        IMG_CHAR *pszRegRegion,
+                                                                                                        IMG_UINT32 ui32RegAddr,
+                                                                                                        IMG_UINT32 ui32RegValue,
+                                                                                                        IMG_UINT32 ui32Mask,
+                                                                                                        IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPol(const PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_CHAR *pszRegRegion,
+                                                                                       IMG_UINT32 ui32RegAddr,
+                                                                                       IMG_UINT32 ui32RegValue,
+                                                                                       IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDReg(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                       IMG_UINT32 ui32RegAddr,
+                                                                                       IMG_UINT32 ui32RegValue);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDDevPAddr(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                               PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+                                                                                               IMG_UINT32 ui32Offset,
+                                                                                               IMG_DEV_PHYADDR sPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPages(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                               IMG_HANDLE                      hKernelMemInfo,
+                                                                                               IMG_DEV_PHYADDR         *pPages,
+                                                                                               IMG_UINT32                      ui32NumPages,
+                                                                                               IMG_DEV_VIRTADDR        sDevAddr,
+                                                                                               IMG_UINT32                      ui32Start,
+                                                                                               IMG_UINT32                      ui32Length,
+                                                                                               IMG_BOOL                        bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSetFrame(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                         IMG_UINT32 ui32Frame);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpComment(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                        IMG_CONST IMG_CHAR *pszComment,
+                                                                                        IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                         IMG_BOOL bContinuous,
+                                                                                         IMG_CONST IMG_CHAR *pszFormat, ...)
+#if !defined(USE_CODE)
+                                                                                         IMG_FORMAT_PRINTF(3, 4)
+#endif
+;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentWithFlagsf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                                          IMG_UINT32 ui32Flags,
+                                                                                                          IMG_CONST IMG_CHAR *pszFormat, ...)
+#if !defined(USE_CODE)
+                                                                                                          IMG_FORMAT_PRINTF(3, 4)
+#endif
+;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpDriverInfo(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                               IMG_CHAR *pszString,
+                                                                                               IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpIsCapturing(IMG_CONST PVRSRV_CONNECTION *psConnection,
+                                                                                               IMG_BOOL *pbIsCapturing);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpBitmap(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_CHAR *pszFileName,
+                                                                                       IMG_UINT32 ui32FileOffset,
+                                                                                       IMG_UINT32 ui32Width,
+                                                                                       IMG_UINT32 ui32Height,
+                                                                                       IMG_UINT32 ui32StrideInBytes,
+                                                                                       IMG_DEV_VIRTADDR sDevBaseAddr,
+                                                                                       IMG_HANDLE hDevMemContext,
+                                                                                       IMG_UINT32 ui32Size,
+                                                                                       PDUMP_PIXEL_FORMAT ePixelFormat,
+                                                                                       PDUMP_MEM_FORMAT eMemFormat,
+                                                                                       IMG_UINT32 ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegRead(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                       IMG_CONST IMG_CHAR *pszRegRegion,
+                                                                                       IMG_CONST IMG_CHAR *pszFileName,
+                                                                                       IMG_UINT32 ui32FileOffset,
+                                                                                       IMG_UINT32 ui32Address,
+                                                                                       IMG_UINT32 ui32Size,
+                                                                                       IMG_UINT32 ui32PDumpFlags);
+
+
+IMG_IMPORT
+IMG_BOOL IMG_CALLCONV PVRSRVPDumpIsCapturingTest(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCycleCountRegRead(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                                               IMG_UINT32 ui32RegOffset,
+                                                                                                               IMG_BOOL bLastFrame);
+
+IMG_IMPORT IMG_HANDLE  PVRSRVLoadLibrary(const IMG_CHAR *pszLibraryName);
+IMG_IMPORT PVRSRV_ERROR        PVRSRVUnloadLibrary(IMG_HANDLE hExtDrv);
+IMG_IMPORT PVRSRV_ERROR        PVRSRVGetLibFuncAddr(IMG_HANDLE hExtDrv, const IMG_CHAR *pszFunctionName, IMG_VOID **ppvFuncAddr);
+
+IMG_IMPORT IMG_UINT32 PVRSRVClockus (void);
+IMG_IMPORT IMG_VOID PVRSRVWaitus (IMG_UINT32 ui32Timeus);
+IMG_IMPORT IMG_VOID PVRSRVReleaseThreadQuanta (void);
+IMG_IMPORT IMG_UINTPTR_T IMG_CALLCONV PVRSRVGetCurrentProcessID(void);
+IMG_IMPORT IMG_CHAR * IMG_CALLCONV PVRSRVSetLocale(const IMG_CHAR *pszLocale);
+
+
+
+
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVCreateAppHintState(IMG_MODULE_ID eModuleID,
+                                                                                                               const IMG_CHAR *pszAppName,
+                                                                                                               IMG_VOID **ppvState);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeAppHintState(IMG_MODULE_ID eModuleID,
+                                                                                IMG_VOID *pvHintState);
+
+IMG_IMPORT IMG_BOOL IMG_CALLCONV PVRSRVGetAppHint(IMG_VOID                     *pvHintState,
+                                                                                                 const IMG_CHAR        *pszHintName,
+                                                                                                 IMG_DATA_TYPE         eDataType,
+                                                                                                 const IMG_VOID        *pvDefault,
+                                                                                                 IMG_VOID                      *pvReturn);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMem (IMG_PVOID pvBase, IMG_SIZE_T uNewSize);
+IMG_IMPORT IMG_VOID  IMG_CALLCONV PVRSRVFreeUserModeMem (IMG_PVOID pvMem);
+IMG_IMPORT IMG_VOID PVRSRVMemCopy(IMG_VOID *pvDst, const IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_VOID PVRSRVMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+struct _PVRSRV_MUTEX_OPAQUE_STRUCT_;
+typedef        struct  _PVRSRV_MUTEX_OPAQUE_STRUCT_ *PVRSRV_MUTEX_HANDLE;
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+
+struct _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_;
+typedef        struct  _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_ *PVRSRV_SEMAPHORE_HANDLE;
+
+
+       #define IMG_SEMAPHORE_WAIT_INFINITE       ((IMG_UINT64)0xFFFFFFFFFFFFFFFFull)
+
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCreateSemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVCreateSemaphore(PVRSRV_SEMAPHORE_HANDLE *phSemaphore, IMG_INT iInitialCount)
+{
+       PVR_UNREFERENCED_PARAMETER(iInitialCount);
+       *phSemaphore = 0;
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVDestroySemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVDestroySemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore)
+{
+       PVR_UNREFERENCED_PARAMETER(hSemaphore);
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVWaitSemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVWaitSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_UINT64 ui64TimeoutMicroSeconds)
+{
+       PVR_UNREFERENCED_PARAMETER(hSemaphore);
+       PVR_UNREFERENCED_PARAMETER(ui64TimeoutMicroSeconds);
+       return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPostSemaphore)
+#endif
+static INLINE IMG_VOID PVRSRVPostSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_INT iPostCount)
+{
+       PVR_UNREFERENCED_PARAMETER(hSemaphore);
+       PVR_UNREFERENCED_PARAMETER(iPostCount);
+}
+
+#endif 
+
+
+#if (defined(DEBUG) && defined(__linux__))
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+
+IMG_IMPORT IMG_VOID  IMG_CALLCONV PVRSRVFreeUserModeMemTracking(IMG_VOID *pvMem);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMemTracking(IMG_VOID *pvMem, IMG_SIZE_T ui32NewSize, 
+                                                                                                         IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+#endif 
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVEventObjectWait(const PVRSRV_CONNECTION *psConnection,
+                                                                       IMG_HANDLE hOSEvent);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateSyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
+                                                                                                        IMG_HANDLE *phKernelSyncInfoModObj);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroySyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
+                                                                                                         IMG_HANDLE hKernelSyncInfoModObj);
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyPendingSyncOps(const PVRSRV_CONNECTION *psConnection,
+                                                                                                         IMG_HANDLE hKernelSyncInfoModObj,
+                                                                                                         PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
+                                                                                                         IMG_UINT32 ui32ModifyFlags,
+                                                                                                         IMG_UINT32 *pui32ReadOpsPending,
+                                                                                                         IMG_UINT32 *pui32WriteOpsPending);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyCompleteSyncOps(const PVRSRV_CONNECTION *psConnection,
+                                                                                                         IMG_HANDLE hKernelSyncInfoModObj);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToModObj(const PVRSRV_CONNECTION *psConnection,
+                                                                                                        IMG_HANDLE hKernelSyncInfoModObj,
+                                                                                                        IMG_BOOL bWait);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToDelta(const PVRSRV_CONNECTION *psConnection,
+                                                                                                       PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+                                                                                                       IMG_UINT32 ui32Delta,
+                                                                                                       IMG_BOOL bWait);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfo(IMG_CONST PVRSRV_DEV_DATA        *psDevData,
+                                                                                         PVRSRV_CLIENT_SYNC_INFO **ppsSyncInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+                                                                                        PVRSRV_CLIENT_SYNC_INFO *psSyncInfo);
+
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError);
+
+
+#define TIME_NOT_PASSED_UINT32(a,b,c)          (((a) - (b)) < (c))
+
+#if defined (__cplusplus)
+}
+#endif
+#endif 
diff --git a/drivers/staging/mrst/pvr/include4/servicesext.h b/drivers/staging/mrst/pvr/include4/servicesext.h
new file mode 100644 (file)
index 0000000..bcd9cfe
--- /dev/null
@@ -0,0 +1,861 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined (__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+#define PVRSRV_LOCKFLG_READONLY        (1)             
+
+typedef enum _PVRSRV_ERROR_
+{
+       PVRSRV_OK = 0,
+       PVRSRV_ERROR_GENERIC,
+       PVRSRV_ERROR_OUT_OF_MEMORY,
+       PVRSRV_ERROR_TOO_FEW_BUFFERS,
+       PVRSRV_ERROR_INVALID_PARAMS,
+       PVRSRV_ERROR_INIT_FAILURE,
+       PVRSRV_ERROR_CANT_REGISTER_CALLBACK,
+       PVRSRV_ERROR_INVALID_DEVICE,
+       PVRSRV_ERROR_NOT_OWNER,
+       PVRSRV_ERROR_BAD_MAPPING,
+       PVRSRV_ERROR_TIMEOUT,
+       PVRSRV_ERROR_FLIP_CHAIN_EXISTS,
+       PVRSRV_ERROR_INVALID_SWAPINTERVAL,
+       PVRSRV_ERROR_SCENE_INVALID,
+       PVRSRV_ERROR_STREAM_ERROR,
+       PVRSRV_ERROR_FAILED_DEPENDENCIES,
+       PVRSRV_ERROR_CMD_NOT_PROCESSED,
+       PVRSRV_ERROR_CMD_TOO_BIG,
+       PVRSRV_ERROR_DEVICE_REGISTER_FAILED,
+       PVRSRV_ERROR_TOOMANYBUFFERS,
+       PVRSRV_ERROR_NOT_SUPPORTED,
+       PVRSRV_ERROR_PROCESSING_BLOCKED,
+
+       PVRSRV_ERROR_CANNOT_FLUSH_QUEUE,
+       PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE,
+       PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS,
+       PVRSRV_ERROR_RETRY,
+
+       PVRSRV_ERROR_DDK_VERSION_MISMATCH,
+       PVRSRV_ERROR_BUILD_MISMATCH,
+       PVRSRV_ERROR_CORE_REVISION_MISMATCH,
+
+       PVRSRV_ERROR_UPLOAD_TOO_BIG,
+
+       PVRSRV_ERROR_INVALID_FLAGS,
+       PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS,
+
+       PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY,
+       PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR,
+       PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED,
+
+       PVRSRV_ERROR_BRIDGE_CALL_FAILED,
+       PVRSRV_ERROR_IOCTL_CALL_FAILED,
+
+    PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND,
+       PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND,
+       PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT,
+
+       PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND,
+       PVRSRV_ERROR_PCI_CALL_FAILED,
+       PVRSRV_ERROR_PCI_REGION_TOO_SMALL,
+       PVRSRV_ERROR_PCI_REGION_UNAVAILABLE,
+       PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH,
+
+       PVRSRV_ERROR_REGISTER_BASE_NOT_SET,
+
+       PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM,
+       PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY,
+       PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC,
+       PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR,
+
+       PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY,
+       PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY,
+
+       PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES,
+       PVRSRV_ERROR_FAILED_TO_FREE_PAGES,
+       PVRSRV_ERROR_FAILED_TO_COPY_PAGES,
+       PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES,
+       PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES,
+       PVRSRV_ERROR_STILL_MAPPED,
+       PVRSRV_ERROR_MAPPING_NOT_FOUND,
+       PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT,
+       PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE,
+
+       PVRSRV_ERROR_INVALID_SEGMENT_BLOCK,
+       PVRSRV_ERROR_INVALID_SGXDEVDATA,
+       PVRSRV_ERROR_INVALID_DEVINFO,
+       PVRSRV_ERROR_INVALID_MEMINFO,
+       PVRSRV_ERROR_INVALID_MISCINFO,
+       PVRSRV_ERROR_UNKNOWN_IOCTL,
+       PVRSRV_ERROR_INVALID_CONTEXT,
+       PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT,
+       PVRSRV_ERROR_INVALID_HEAP,
+       PVRSRV_ERROR_INVALID_KERNELINFO,
+       PVRSRV_ERROR_UNKNOWN_POWER_STATE,
+       PVRSRV_ERROR_INVALID_HANDLE_TYPE,
+       PVRSRV_ERROR_INVALID_WRAP_TYPE,
+       PVRSRV_ERROR_INVALID_PHYS_ADDR,
+       PVRSRV_ERROR_INVALID_CPU_ADDR,
+       PVRSRV_ERROR_INVALID_HEAPINFO,
+       PVRSRV_ERROR_INVALID_PERPROC,
+       PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO,
+       PVRSRV_ERROR_INVALID_MAP_REQUEST,
+       PVRSRV_ERROR_INVALID_UNMAP_REQUEST,
+       PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP,
+       PVRSRV_ERROR_MAPPING_STILL_IN_USE,
+
+       PVRSRV_ERROR_EXCEEDED_HW_LIMITS,
+       PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED,
+
+       PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA,
+       PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT,
+       PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT,
+       PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT,
+       PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT,
+       PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD,
+       PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD,
+       PVRSRV_ERROR_THREAD_READ_ERROR,
+       PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER,
+       PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR,
+       PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR,
+       PVRSRV_ERROR_ISR_ALREADY_INSTALLED,
+       PVRSRV_ERROR_ISR_NOT_INSTALLED,
+       PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT,
+       PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO,
+       PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT,
+       PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES,
+       PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT,
+       PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE,
+
+       PVRSRV_ERROR_INVALID_CCB_COMMAND,
+
+       PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE,
+       PVRSRV_ERROR_INVALID_LOCK_ID,
+       PVRSRV_ERROR_RESOURCE_NOT_LOCKED,
+
+       PVRSRV_ERROR_FLIP_FAILED,
+       PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED,
+
+       PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE,
+
+       PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED,
+       PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG,
+       PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG,
+       PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG,
+
+       PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID,
+
+       PVRSRV_ERROR_BLIT_SETUP_FAILED,
+
+       PVRSRV_ERROR_PDUMP_NOT_AVAILABLE,
+       PVRSRV_ERROR_PDUMP_BUFFER_FULL,
+       PVRSRV_ERROR_PDUMP_BUF_OVERFLOW,
+       PVRSRV_ERROR_PDUMP_NOT_ACTIVE,
+       PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES,
+
+       PVRSRV_ERROR_MUTEX_DESTROY_FAILED,
+       PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR,
+
+       PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE,
+       PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND,
+
+       PVRSRV_ERROR_PROCESS_NOT_INITIALISED,
+       PVRSRV_ERROR_PROCESS_NOT_FOUND,
+       PVRSRV_ERROR_SRV_CONNECT_FAILED,
+       PVRSRV_ERROR_SRV_DISCONNECT_FAILED,
+       PVRSRV_ERROR_DEINT_PHASE_FAILED,
+       PVRSRV_ERROR_INIT2_PHASE_FAILED,
+
+       PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE,
+
+       PVRSRV_ERROR_NO_DC_DEVICES_FOUND,
+       PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE,
+       PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE,
+       PVRSRV_ERROR_NO_DEVICEDATA_FOUND,
+       PVRSRV_ERROR_NO_DEVICENODE_FOUND,
+       PVRSRV_ERROR_NO_CLIENTNODE_FOUND,
+       PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE,
+
+       PVRSRV_ERROR_UNABLE_TO_INIT_TASK,
+       PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK,
+       PVRSRV_ERROR_UNABLE_TO_KILL_TASK,
+
+       PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER,
+       PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER,
+       PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER,
+
+       PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT,
+       PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION,
+
+       PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE,
+       PVRSRV_ERROR_HANDLE_NOT_ALLOCATED,
+       PVRSRV_ERROR_HANDLE_TYPE_MISMATCH,
+       PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE,
+       PVRSRV_ERROR_HANDLE_NOT_SHAREABLE,
+       PVRSRV_ERROR_HANDLE_NOT_FOUND,
+       PVRSRV_ERROR_INVALID_SUBHANDLE,
+       PVRSRV_ERROR_HANDLE_BATCH_IN_USE,
+       PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE,
+
+       PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE,
+       PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED,
+
+       PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE,
+       PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP,
+
+       PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE,
+
+       PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE,
+       PVRSRV_ERROR_INVALID_DEVICEID,
+       PVRSRV_ERROR_DEVICEID_NOT_FOUND,
+
+       PVRSRV_ERROR_MEMORY_TEST_FAILED,
+       PVRSRV_ERROR_CPUPADDR_TEST_FAILED,
+       PVRSRV_ERROR_COPY_TEST_FAILED,
+
+       PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED,
+
+       PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK,
+       PVRSRV_ERROR_CLOCK_REQUEST_FAILED,
+       PVRSRV_ERROR_DISABLE_CLOCK_FAILURE,
+       PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE,
+       PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE,
+       PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK,
+       PVRSRV_ERROR_UNABLE_TO_GET_CLOCK,
+       PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK,
+       PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK,
+
+       PVRSRV_ERROR_UNKNOWN_SGL_ERROR,
+
+       PVRSRV_ERROR_SYSTEM_POWER_CHANGE_FAILURE,
+       PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE,
+
+       PVRSRV_ERROR_BAD_SYNC_STATE,
+
+       PVRSRV_ERROR_CACHEOP_FAILED,
+
+       PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_ERROR;
+
+
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+       PVRSRV_DEVICE_CLASS_3D                          = 0 ,
+       PVRSRV_DEVICE_CLASS_DISPLAY                     = 1 ,
+       PVRSRV_DEVICE_CLASS_BUFFER                      = 2 ,
+       PVRSRV_DEVICE_CLASS_VIDEO                       = 3 ,
+
+       PVRSRV_DEVICE_CLASS_FORCE_I32           = 0x7fffffff
+
+} PVRSRV_DEVICE_CLASS;
+
+
+typedef enum _PVRSRV_SYS_POWER_STATE_
+{
+       PVRSRV_SYS_POWER_STATE_Unspecified              = -1,   
+       PVRSRV_SYS_POWER_STATE_D0                               = 0,    
+       PVRSRV_SYS_POWER_STATE_D1                               = 1,    
+       PVRSRV_SYS_POWER_STATE_D2                               = 2,    
+       PVRSRV_SYS_POWER_STATE_D3                               = 3,    
+       PVRSRV_SYS_POWER_STATE_D4                               = 4,    
+
+       PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_SYS_POWER_STATE, *PPVRSRV_SYS_POWER_STATE;
+
+
+typedef enum _PVRSRV_DEV_POWER_STATE_
+{
+       PVRSRV_DEV_POWER_STATE_DEFAULT  = -1,   
+       PVRSRV_DEV_POWER_STATE_ON               = 0,    
+       PVRSRV_DEV_POWER_STATE_IDLE             = 1,    
+       PVRSRV_DEV_POWER_STATE_OFF              = 2,    
+
+       PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE;    
+
+
+typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE                              hDevHandle,
+                                                                          PVRSRV_DEV_POWER_STATE       eNewPowerState,
+                                                                          PVRSRV_DEV_POWER_STATE       eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE                             hDevHandle,
+                                                                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                                                                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+
+typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE                          hDevHandle,
+                                                                                                  IMG_BOOL                                     bIdleDevice,
+                                                                                                  PVRSRV_DEV_POWER_STATE       eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE                         hDevHandle,
+                                                                                                       IMG_BOOL                                bIdleDevice,
+                                                                                                       PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+
+
+typedef enum _PVRSRV_PIXEL_FORMAT_ {
+       
+       PVRSRV_PIXEL_FORMAT_UNKNOWN                             =  0,
+       PVRSRV_PIXEL_FORMAT_RGB565                              =  1,
+       PVRSRV_PIXEL_FORMAT_RGB555                              =  2,
+       PVRSRV_PIXEL_FORMAT_RGB888                              =  3,   
+       PVRSRV_PIXEL_FORMAT_BGR888                              =  4,   
+       PVRSRV_PIXEL_FORMAT_GREY_SCALE                  =  8,
+       PVRSRV_PIXEL_FORMAT_PAL12                               = 13,
+       PVRSRV_PIXEL_FORMAT_PAL8                                = 14,
+       PVRSRV_PIXEL_FORMAT_PAL4                                = 15,
+       PVRSRV_PIXEL_FORMAT_PAL2                                = 16,
+       PVRSRV_PIXEL_FORMAT_PAL1                                = 17,
+       PVRSRV_PIXEL_FORMAT_ARGB1555                    = 18,
+       PVRSRV_PIXEL_FORMAT_ARGB4444                    = 19,
+       PVRSRV_PIXEL_FORMAT_ARGB8888                    = 20,
+       PVRSRV_PIXEL_FORMAT_ABGR8888                    = 21,
+       PVRSRV_PIXEL_FORMAT_YV12                                = 22,
+       PVRSRV_PIXEL_FORMAT_I420                                = 23,
+    PVRSRV_PIXEL_FORMAT_IMC2                           = 25,
+       PVRSRV_PIXEL_FORMAT_XRGB8888                    = 26,
+       PVRSRV_PIXEL_FORMAT_XBGR8888                    = 27,
+       PVRSRV_PIXEL_FORMAT_BGRA8888                    = 28,
+       PVRSRV_PIXEL_FORMAT_XRGB4444                    = 29,
+       PVRSRV_PIXEL_FORMAT_ARGB8332                    = 30,
+       PVRSRV_PIXEL_FORMAT_A2RGB10                             = 31,   
+       PVRSRV_PIXEL_FORMAT_A2BGR10                             = 32,   
+       PVRSRV_PIXEL_FORMAT_P8                                  = 33,
+       PVRSRV_PIXEL_FORMAT_L8                                  = 34,
+       PVRSRV_PIXEL_FORMAT_A8L8                                = 35,
+       PVRSRV_PIXEL_FORMAT_A4L4                                = 36,
+       PVRSRV_PIXEL_FORMAT_L16                                 = 37,
+       PVRSRV_PIXEL_FORMAT_L6V5U5                              = 38,
+       PVRSRV_PIXEL_FORMAT_V8U8                                = 39,
+       PVRSRV_PIXEL_FORMAT_V16U16                              = 40,
+       PVRSRV_PIXEL_FORMAT_QWVU8888                    = 41,
+       PVRSRV_PIXEL_FORMAT_XLVU8888                    = 42,
+       PVRSRV_PIXEL_FORMAT_QWVU16                              = 43,
+       PVRSRV_PIXEL_FORMAT_D16                                 = 44,
+       PVRSRV_PIXEL_FORMAT_D24S8                               = 45,
+       PVRSRV_PIXEL_FORMAT_D24X8                               = 46,
+
+       
+       PVRSRV_PIXEL_FORMAT_ABGR16                              = 47,
+       PVRSRV_PIXEL_FORMAT_ABGR16F                             = 48,
+       PVRSRV_PIXEL_FORMAT_ABGR32                              = 49,
+       PVRSRV_PIXEL_FORMAT_ABGR32F                             = 50,
+       PVRSRV_PIXEL_FORMAT_B10GR11                             = 51,
+       PVRSRV_PIXEL_FORMAT_GR88                                = 52,
+       PVRSRV_PIXEL_FORMAT_BGR32                               = 53,
+       PVRSRV_PIXEL_FORMAT_GR32                                = 54,
+       PVRSRV_PIXEL_FORMAT_E5BGR9                              = 55,
+
+       
+       PVRSRV_PIXEL_FORMAT_RESERVED1                   = 56,
+       PVRSRV_PIXEL_FORMAT_RESERVED2                   = 57,
+       PVRSRV_PIXEL_FORMAT_RESERVED3                   = 58,
+       PVRSRV_PIXEL_FORMAT_RESERVED4                   = 59,
+       PVRSRV_PIXEL_FORMAT_RESERVED5                   = 60,
+
+       
+       PVRSRV_PIXEL_FORMAT_R8G8_B8G8                   = 61,
+       PVRSRV_PIXEL_FORMAT_G8R8_G8B8                   = 62,
+
+       
+       PVRSRV_PIXEL_FORMAT_NV11                                = 63,
+       PVRSRV_PIXEL_FORMAT_NV12                                = 64,
+
+       
+       PVRSRV_PIXEL_FORMAT_YUY2                                = 65,
+       PVRSRV_PIXEL_FORMAT_YUV420                              = 66,
+       PVRSRV_PIXEL_FORMAT_YUV444                              = 67,
+       PVRSRV_PIXEL_FORMAT_VUY444                              = 68,
+       PVRSRV_PIXEL_FORMAT_YUYV                                = 69,
+       PVRSRV_PIXEL_FORMAT_YVYU                                = 70,
+       PVRSRV_PIXEL_FORMAT_UYVY                                = 71,
+       PVRSRV_PIXEL_FORMAT_VYUY                                = 72,
+
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY             = 73,   
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV             = 74,   
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU             = 75,   
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY             = 76,   
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV             = 77,   
+
+       
+       PVRSRV_PIXEL_FORMAT_A32B32G32R32                = 78,   
+       PVRSRV_PIXEL_FORMAT_A32B32G32R32F               = 79,   
+       PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT   = 80,   
+       PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT   = 81,   
+
+       
+       PVRSRV_PIXEL_FORMAT_B32G32R32                   = 82,   
+       PVRSRV_PIXEL_FORMAT_B32G32R32F                  = 83,   
+       PVRSRV_PIXEL_FORMAT_B32G32R32_UINT              = 84,   
+       PVRSRV_PIXEL_FORMAT_B32G32R32_SINT              = 85,   
+
+       
+       PVRSRV_PIXEL_FORMAT_G32R32                              = 86,   
+       PVRSRV_PIXEL_FORMAT_G32R32F                             = 87,   
+       PVRSRV_PIXEL_FORMAT_G32R32_UINT                 = 88,   
+       PVRSRV_PIXEL_FORMAT_G32R32_SINT                 = 89,   
+
+       
+       PVRSRV_PIXEL_FORMAT_D32F                                = 90,   
+       PVRSRV_PIXEL_FORMAT_R32                                 = 91,   
+       PVRSRV_PIXEL_FORMAT_R32F                                = 92,   
+       PVRSRV_PIXEL_FORMAT_R32_UINT                    = 93,   
+       PVRSRV_PIXEL_FORMAT_R32_SINT                    = 94,   
+
+       
+       PVRSRV_PIXEL_FORMAT_A16B16G16R16                = 95,   
+       PVRSRV_PIXEL_FORMAT_A16B16G16R16F               = 96,   
+       PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT   = 97,   
+       PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM  = 98,   
+       PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT   = 99,   
+       PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM  = 100,  
+
+       
+       PVRSRV_PIXEL_FORMAT_G16R16                              = 101,  
+       PVRSRV_PIXEL_FORMAT_G16R16F                             = 102,  
+       PVRSRV_PIXEL_FORMAT_G16R16_UINT                 = 103,  
+       PVRSRV_PIXEL_FORMAT_G16R16_UNORM                = 104,  
+       PVRSRV_PIXEL_FORMAT_G16R16_SINT                 = 105,  
+       PVRSRV_PIXEL_FORMAT_G16R16_SNORM                = 106,  
+
+       
+       PVRSRV_PIXEL_FORMAT_R16                                 = 107,  
+       PVRSRV_PIXEL_FORMAT_R16F                                = 108,  
+       PVRSRV_PIXEL_FORMAT_R16_UINT                    = 109,  
+       PVRSRV_PIXEL_FORMAT_R16_UNORM                   = 110,  
+       PVRSRV_PIXEL_FORMAT_R16_SINT                    = 111,  
+       PVRSRV_PIXEL_FORMAT_R16_SNORM                   = 112,  
+
+       
+       PVRSRV_PIXEL_FORMAT_X8R8G8B8                    = 113,  
+       PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM              = 114,  
+       PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB = 115,  
+
+       PVRSRV_PIXEL_FORMAT_A8R8G8B8                    = 116,  
+       PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM              = 117,  
+       PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB = 118,  
+
+       PVRSRV_PIXEL_FORMAT_A8B8G8R8                    = 119,  
+       PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT               = 120,  
+       PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM              = 121,  
+       PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB = 122,  
+       PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT               = 123,  
+       PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM              = 124,  
+
+       
+       PVRSRV_PIXEL_FORMAT_G8R8                                = 125,  
+       PVRSRV_PIXEL_FORMAT_G8R8_UINT                   = 126,  
+       PVRSRV_PIXEL_FORMAT_G8R8_UNORM                  = 127,  
+       PVRSRV_PIXEL_FORMAT_G8R8_SINT                   = 128,  
+       PVRSRV_PIXEL_FORMAT_G8R8_SNORM                  = 129,  
+
+       
+       PVRSRV_PIXEL_FORMAT_A8                                  = 130,  
+       PVRSRV_PIXEL_FORMAT_R8                                  = 131,  
+       PVRSRV_PIXEL_FORMAT_R8_UINT                             = 132,  
+       PVRSRV_PIXEL_FORMAT_R8_UNORM                    = 133,  
+       PVRSRV_PIXEL_FORMAT_R8_SINT                             = 134,  
+       PVRSRV_PIXEL_FORMAT_R8_SNORM                    = 135,  
+
+       
+       PVRSRV_PIXEL_FORMAT_A2B10G10R10                 = 136,  
+       PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM   = 137,  
+       PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT    = 138,  
+
+       
+       PVRSRV_PIXEL_FORMAT_B10G11R11                   = 139,  
+       PVRSRV_PIXEL_FORMAT_B10G11R11F                  = 140,  
+
+       
+       PVRSRV_PIXEL_FORMAT_X24G8R32                    = 141,  
+       PVRSRV_PIXEL_FORMAT_G8R24                               = 142,  
+       PVRSRV_PIXEL_FORMAT_X8R24                               = 143,
+       PVRSRV_PIXEL_FORMAT_E5B9G9R9                    = 144,  
+       PVRSRV_PIXEL_FORMAT_R1                                  = 145,  
+
+       PVRSRV_PIXEL_FORMAT_RESERVED6                   = 146,
+       PVRSRV_PIXEL_FORMAT_RESERVED7                   = 147,
+       PVRSRV_PIXEL_FORMAT_RESERVED8                   = 148,
+       PVRSRV_PIXEL_FORMAT_RESERVED9                   = 149,
+       PVRSRV_PIXEL_FORMAT_RESERVED10                  = 150,
+       PVRSRV_PIXEL_FORMAT_RESERVED11                  = 151,
+       PVRSRV_PIXEL_FORMAT_RESERVED12                  = 152,
+       PVRSRV_PIXEL_FORMAT_RESERVED13                  = 153,
+       PVRSRV_PIXEL_FORMAT_RESERVED14                  = 154,
+       PVRSRV_PIXEL_FORMAT_RESERVED15                  = 155,
+       PVRSRV_PIXEL_FORMAT_RESERVED16                  = 156,
+       PVRSRV_PIXEL_FORMAT_RESERVED17                  = 157,
+       PVRSRV_PIXEL_FORMAT_RESERVED18                  = 158,
+       PVRSRV_PIXEL_FORMAT_RESERVED19                  = 159,
+       PVRSRV_PIXEL_FORMAT_RESERVED20                  = 160,
+
+       
+       PVRSRV_PIXEL_FORMAT_UBYTE4                              = 161,  
+       PVRSRV_PIXEL_FORMAT_SHORT4                              = 162,  
+       PVRSRV_PIXEL_FORMAT_SHORT4N                             = 163,  
+       PVRSRV_PIXEL_FORMAT_USHORT4N                    = 164,  
+       PVRSRV_PIXEL_FORMAT_SHORT2N                             = 165,  
+       PVRSRV_PIXEL_FORMAT_SHORT2                              = 166,  
+       PVRSRV_PIXEL_FORMAT_USHORT2N                    = 167,  
+       PVRSRV_PIXEL_FORMAT_UDEC3                               = 168,  
+       PVRSRV_PIXEL_FORMAT_DEC3N                               = 169,  
+       PVRSRV_PIXEL_FORMAT_F16_2                               = 170,  
+       PVRSRV_PIXEL_FORMAT_F16_4                               = 171,  
+
+       
+       PVRSRV_PIXEL_FORMAT_L_F16                               = 172,
+       PVRSRV_PIXEL_FORMAT_L_F16_REP                   = 173,
+       PVRSRV_PIXEL_FORMAT_L_F16_A_F16                 = 174,
+       PVRSRV_PIXEL_FORMAT_A_F16                               = 175,
+       PVRSRV_PIXEL_FORMAT_B16G16R16F                  = 176,
+
+       PVRSRV_PIXEL_FORMAT_L_F32                               = 177,
+       PVRSRV_PIXEL_FORMAT_A_F32                               = 178,
+       PVRSRV_PIXEL_FORMAT_L_F32_A_F32                 = 179,
+
+       
+       PVRSRV_PIXEL_FORMAT_PVRTC2                              = 180,
+       PVRSRV_PIXEL_FORMAT_PVRTC4                              = 181,
+       PVRSRV_PIXEL_FORMAT_PVRTCII2                    = 182,
+       PVRSRV_PIXEL_FORMAT_PVRTCII4                    = 183,
+       PVRSRV_PIXEL_FORMAT_PVRTCIII                    = 184,
+       PVRSRV_PIXEL_FORMAT_PVRO8                               = 185,
+       PVRSRV_PIXEL_FORMAT_PVRO88                              = 186,
+       PVRSRV_PIXEL_FORMAT_PT1                                 = 187,
+       PVRSRV_PIXEL_FORMAT_PT2                                 = 188,
+       PVRSRV_PIXEL_FORMAT_PT4                                 = 189,
+       PVRSRV_PIXEL_FORMAT_PT8                                 = 190,
+       PVRSRV_PIXEL_FORMAT_PTW                                 = 191,
+       PVRSRV_PIXEL_FORMAT_PTB                                 = 192,
+       PVRSRV_PIXEL_FORMAT_MONO8                               = 193,
+       PVRSRV_PIXEL_FORMAT_MONO16                              = 194,
+
+       
+       PVRSRV_PIXEL_FORMAT_C0_YUYV                             = 195,
+       PVRSRV_PIXEL_FORMAT_C0_UYVY                             = 196,
+       PVRSRV_PIXEL_FORMAT_C0_YVYU                             = 197,
+       PVRSRV_PIXEL_FORMAT_C0_VYUY                             = 198,
+       PVRSRV_PIXEL_FORMAT_C1_YUYV                             = 199,
+       PVRSRV_PIXEL_FORMAT_C1_UYVY                             = 200,
+       PVRSRV_PIXEL_FORMAT_C1_YVYU                             = 201,
+       PVRSRV_PIXEL_FORMAT_C1_VYUY                             = 202,
+
+       
+       PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_UV             = 203,
+       PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_VU             = 204,
+       PVRSRV_PIXEL_FORMAT_C0_YUV420_3P                = 205,
+       PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_UV             = 206,
+       PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_VU             = 207,
+       PVRSRV_PIXEL_FORMAT_C1_YUV420_3P                = 208,
+
+       PVRSRV_PIXEL_FORMAT_A2B10G10R10F                = 209,
+       PVRSRV_PIXEL_FORMAT_B8G8R8_SINT                 = 210,
+       PVRSRV_PIXEL_FORMAT_PVRF32SIGNMASK              = 211,
+       
+       PVRSRV_PIXEL_FORMAT_ABGR4444                    = 212,  
+       PVRSRV_PIXEL_FORMAT_ABGR1555                    = 213,
+       PVRSRV_PIXEL_FORMAT_BGR565                              = 214,                  
+
+       PVRSRV_PIXEL_FORMAT_FORCE_I32                   = 0x7fffffff
+
+} PVRSRV_PIXEL_FORMAT;
+
+typedef enum _PVRSRV_ALPHA_FORMAT_ {
+       PVRSRV_ALPHA_FORMAT_UNKNOWN             =  0x00000000,
+       PVRSRV_ALPHA_FORMAT_PRE                 =  0x00000001,
+       PVRSRV_ALPHA_FORMAT_NONPRE              =  0x00000002,
+       PVRSRV_ALPHA_FORMAT_MASK                =  0x0000000F,
+} PVRSRV_ALPHA_FORMAT;
+
+typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
+       PVRSRV_COLOURSPACE_FORMAT_UNKNOWN               =  0x00000000,
+       PVRSRV_COLOURSPACE_FORMAT_LINEAR                =  0x00010000,
+       PVRSRV_COLOURSPACE_FORMAT_NONLINEAR             =  0x00020000,
+       PVRSRV_COLOURSPACE_FORMAT_MASK                  =  0x000F0000,
+} PVRSRV_COLOURSPACE_FORMAT;
+
+
+typedef enum _PVRSRV_ROTATION_ {
+       PVRSRV_ROTATE_0         =       0,
+       PVRSRV_ROTATE_90        =       1,
+       PVRSRV_ROTATE_180       =       2,
+       PVRSRV_ROTATE_270       =       3,
+       PVRSRV_FLIP_Y
+
+} PVRSRV_ROTATION;
+
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED         (1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY          (1<<1)
+#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY     (1<<2)
+
+typedef struct _PVRSRV_SYNC_DATA_
+{
+       
+       IMG_UINT32                                      ui32WriteOpsPending;
+       volatile IMG_UINT32                     ui32WriteOpsComplete;
+
+       
+       IMG_UINT32                                      ui32ReadOpsPending;
+       volatile IMG_UINT32                     ui32ReadOpsComplete;
+
+       
+       IMG_UINT32                                      ui32LastOpDumpVal;
+       IMG_UINT32                                      ui32LastReadOpDumpVal;
+
+} PVRSRV_SYNC_DATA;
+
+typedef struct _PVRSRV_CLIENT_SYNC_INFO_
+{
+       
+       PVRSRV_SYNC_DATA                        *psSyncData;
+
+       
+
+
+       
+       IMG_DEV_VIRTADDR                sWriteOpsCompleteDevVAddr;
+
+       
+       IMG_DEV_VIRTADDR                sReadOpsCompleteDevVAddr;
+
+       
+       IMG_HANDLE                                      hMappingInfo;
+
+       
+       IMG_HANDLE                                      hKernelSyncInfo;
+
+} PVRSRV_CLIENT_SYNC_INFO, *PPVRSRV_CLIENT_SYNC_INFO;
+
+typedef struct PVRSRV_RESOURCE_TAG
+{
+       volatile IMG_UINT32 ui32Lock;
+       IMG_UINT32                      ui32ID;
+}PVRSRV_RESOURCE;
+typedef PVRSRV_RESOURCE PVRSRV_RES_HANDLE;
+
+
+typedef IMG_VOID (*PFN_CMD_COMPLETE) (IMG_HANDLE);
+typedef IMG_VOID (**PPFN_CMD_COMPLETE) (IMG_HANDLE);
+
+typedef IMG_BOOL (*PFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+typedef IMG_BOOL (**PPFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+
+
+typedef struct _IMG_RECT_
+{
+       IMG_INT32       x0;
+       IMG_INT32       y0;
+       IMG_INT32       x1;
+       IMG_INT32       y1;
+}IMG_RECT;
+
+typedef struct _IMG_RECT_16_
+{
+       IMG_INT16       x0;
+       IMG_INT16       y0;
+       IMG_INT16       x1;
+       IMG_INT16       y1;
+}IMG_RECT_16;
+
+
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ADDR)(IMG_HANDLE,
+                                                                                       IMG_HANDLE,
+                                                                                       IMG_SYS_PHYADDR**,
+                                                                                       IMG_SIZE_T*,
+                                                                                       IMG_VOID**,
+                                                                                       IMG_HANDLE*,
+                                                                                       IMG_BOOL*,
+                                                                                       IMG_UINT32*);
+
+
+typedef struct DISPLAY_DIMS_TAG
+{
+       IMG_UINT32      ui32ByteStride;
+       IMG_UINT32      ui32Width;
+       IMG_UINT32      ui32Height;
+} DISPLAY_DIMS;
+
+
+typedef struct DISPLAY_FORMAT_TAG
+{
+       
+       PVRSRV_PIXEL_FORMAT             pixelformat;
+} DISPLAY_FORMAT;
+
+typedef struct DISPLAY_SURF_ATTRIBUTES_TAG
+{
+       
+       PVRSRV_PIXEL_FORMAT             pixelformat;
+       
+       DISPLAY_DIMS                    sDims;
+} DISPLAY_SURF_ATTRIBUTES;
+
+
+typedef struct DISPLAY_MODE_INFO_TAG
+{
+       
+       PVRSRV_PIXEL_FORMAT             pixelformat;
+       
+       DISPLAY_DIMS                    sDims;
+       
+       IMG_UINT32                              ui32RefreshHZ;
+       
+       IMG_UINT32                              ui32OEMFlags;
+} DISPLAY_MODE_INFO;
+
+
+
+#define MAX_DISPLAY_NAME_SIZE  (50) 
+
+typedef struct DISPLAY_INFO_TAG
+{
+       
+       IMG_UINT32 ui32MaxSwapChains;
+       
+       IMG_UINT32 ui32MaxSwapChainBuffers;
+       
+       IMG_UINT32 ui32MinSwapInterval;
+       
+       IMG_UINT32 ui32MaxSwapInterval;
+       
+       IMG_UINT32 ui32PhysicalWidthmm;
+       IMG_UINT32 ui32PhysicalHeightmm;
+       
+       IMG_CHAR        szDisplayName[MAX_DISPLAY_NAME_SIZE];
+#if defined(SUPPORT_HW_CURSOR)
+       
+       IMG_UINT16      ui32CursorWidth;
+       IMG_UINT16      ui32CursorHeight;
+#endif
+} DISPLAY_INFO;
+
+typedef struct ACCESS_INFO_TAG
+{
+       IMG_UINT32              ui32Size;
+       IMG_UINT32      ui32FBPhysBaseAddress;
+       IMG_UINT32              ui32FBMemAvailable;                     
+       IMG_UINT32      ui32SysPhysBaseAddress;
+       IMG_UINT32              ui32SysSize;
+       IMG_UINT32              ui32DevIRQ;
+}ACCESS_INFO;
+
+
+typedef struct PVRSRV_CURSOR_SHAPE_TAG
+{
+       IMG_UINT16                      ui16Width;
+       IMG_UINT16                      ui16Height;
+       IMG_INT16                       i16XHot;
+       IMG_INT16                       i16YHot;
+
+       
+       IMG_VOID*               pvMask;
+       IMG_INT16                       i16MaskByteStride;
+
+       
+       IMG_VOID*                       pvColour;
+       IMG_INT16                       i16ColourByteStride;
+       PVRSRV_PIXEL_FORMAT     eColourPixelFormat;
+} PVRSRV_CURSOR_SHAPE;
+
+#define PVRSRV_SET_CURSOR_VISIBILITY   (1<<0)
+#define PVRSRV_SET_CURSOR_POSITION             (1<<1)
+#define PVRSRV_SET_CURSOR_SHAPE                        (1<<2)
+#define PVRSRV_SET_CURSOR_ROTATION             (1<<3)
+
+typedef struct PVRSRV_CURSOR_INFO_TAG
+{
+       
+       IMG_UINT32 ui32Flags;
+
+       
+       IMG_BOOL bVisible;
+
+       
+       IMG_INT16 i16XPos;
+       IMG_INT16 i16YPos;
+
+       
+       PVRSRV_CURSOR_SHAPE sCursorShape;
+
+       
+       IMG_UINT32 ui32Rotation;
+
+} PVRSRV_CURSOR_INFO;
+
+#if defined(PDUMP_SUSPEND_IS_PER_THREAD)
+typedef struct {
+       IMG_UINT32 threadId;
+       int suspendCount;
+} PVRSRV_THREAD_SUSPEND_COUNT;
+
+#define PVRSRV_PDUMP_SUSPEND_Q_NAME "PVRSRVPDumpSuspendMsgQ"
+#define PVRSRV_PDUMP_SUSPEND_Q_LENGTH 8
+
+#endif
+
+typedef struct _PVRSRV_REGISTRY_INFO_
+{
+    IMG_UINT32         ui32DevCookie;
+    IMG_PCHAR          pszKey;
+    IMG_PCHAR          pszValue;
+    IMG_PCHAR          pszBuf;
+    IMG_UINT32         ui32BufSize;
+} PVRSRV_REGISTRY_INFO, *PPVRSRV_REGISTRY_INFO;
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReadRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWriteRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+#define PVRSRV_BC_FLAGS_YUVCSC_CONFORMANT_RANGE        (0 << 0)
+#define PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE              (1 << 0)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_BT601                   (0 << 1)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT709                   (1 << 1)
+
+#define MAX_BUFFER_DEVICE_NAME_SIZE    (50) 
+
+typedef struct BUFFER_INFO_TAG
+{
+       IMG_UINT32                      ui32BufferCount;
+       IMG_UINT32                      ui32BufferDeviceID;
+       PVRSRV_PIXEL_FORMAT     pixelformat;
+       IMG_UINT32                      ui32ByteStride;
+       IMG_UINT32                      ui32Width;
+       IMG_UINT32                      ui32Height;
+       IMG_UINT32                      ui32Flags;
+       IMG_CHAR                        szDeviceName[MAX_BUFFER_DEVICE_NAME_SIZE];
+} BUFFER_INFO;
+
+typedef enum _OVERLAY_DEINTERLACE_MODE_
+{
+       WEAVE=0x0,
+       BOB_ODD,
+       BOB_EVEN,
+       BOB_EVEN_NONINTERLEAVED
+} OVERLAY_DEINTERLACE_MODE;
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/include4/sgx_options.h b/drivers/staging/mrst/pvr/include4/sgx_options.h
new file mode 100644 (file)
index 0000000..5777bae
--- /dev/null
@@ -0,0 +1,237 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+#define DEBUG_SET_OFFSET       OPTIONS_BIT0
+#define OPTIONS_BIT0           0x1
+#else
+#define OPTIONS_BIT0           0x0
+#endif
+
+#if defined(PDUMP) || defined (INTERNAL_TEST)
+#define PDUMP_SET_OFFSET       OPTIONS_BIT1
+#define OPTIONS_BIT1           (0x1 << 1)
+#else
+#define OPTIONS_BIT1           0x0
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined (INTERNAL_TEST)
+#define PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET                OPTIONS_BIT2
+#define OPTIONS_BIT2           (0x1 << 2)
+#else
+#define OPTIONS_BIT2           0x0
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY) || defined (INTERNAL_TEST)
+#define SUPPORT_HW_RECOVERY_SET_OFFSET OPTIONS_BIT3
+#define OPTIONS_BIT3           (0x1 << 3)
+#else
+#define OPTIONS_BIT3           0x0
+#endif
+
+
+
+#if defined(PVR_SECURE_HANDLES) || defined (INTERNAL_TEST)
+#define PVR_SECURE_HANDLES_SET_OFFSET  OPTIONS_BIT4
+#define OPTIONS_BIT4           (0x1 << 4)
+#else
+#define OPTIONS_BIT4           0x0
+#endif
+
+#if defined(SGX_BYPASS_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_BYPASS_SYSTEM_CACHE_SET_OFFSET     OPTIONS_BIT5
+#define OPTIONS_BIT5           (0x1 << 5)
+#else
+#define OPTIONS_BIT5           0x0
+#endif
+
+#if defined(SGX_DMS_AGE_ENABLE) || defined (INTERNAL_TEST)
+#define SGX_DMS_AGE_ENABLE_SET_OFFSET  OPTIONS_BIT6
+#define OPTIONS_BIT6           (0x1 << 6)
+#else
+#define OPTIONS_BIT6           0x0
+#endif
+
+#if defined(SGX_FAST_DPM_INIT) || defined (INTERNAL_TEST)
+#define SGX_FAST_DPM_INIT_SET_OFFSET   OPTIONS_BIT8
+#define OPTIONS_BIT8           (0x1 << 8)
+#else
+#define OPTIONS_BIT8           0x0
+#endif
+
+#if defined(SGX_FEATURE_WRITEBACK_DCU) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_DCU_SET_OFFSET     OPTIONS_BIT9
+#define OPTIONS_BIT9           (0x1 << 9)
+#else
+#define OPTIONS_BIT9           0x0
+#endif
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MP_SET_OFFSET      OPTIONS_BIT10
+#define OPTIONS_BIT10          (0x1 << 10)
+#else
+#define OPTIONS_BIT10          0x0
+#endif
+
+#if defined(SGX_FEATURE_MULTITHREADED_UKERNEL) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MULTITHREADED_UKERNEL_SET_OFFSET   OPTIONS_BIT11
+#define OPTIONS_BIT11          (0x1 << 11)
+#else
+#define OPTIONS_BIT11          0x0
+#endif
+
+
+
+#if defined(SGX_FEATURE_OVERLAPPED_SPM) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_OVERLAPPED_SPM_SET_OFFSET  OPTIONS_BIT12
+#define OPTIONS_BIT12          (0x1 << 12)
+#else
+#define OPTIONS_BIT12          0x0
+#endif
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_SYSTEM_CACHE_SET_OFFSET    OPTIONS_BIT13
+#define OPTIONS_BIT13          (0x1 << 13)
+#else
+#define OPTIONS_BIT13          0x0
+#endif
+
+#if defined(SGX_SUPPORT_HWPROFILING) || defined (INTERNAL_TEST)
+#define SGX_SUPPORT_HWPROFILING_SET_OFFSET     OPTIONS_BIT14
+#define OPTIONS_BIT14          (0x1 << 14)
+#else
+#define OPTIONS_BIT14          0x0
+#endif
+
+
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) || defined (INTERNAL_TEST)
+#define SUPPORT_ACTIVE_POWER_MANAGEMENT_SET_OFFSET     OPTIONS_BIT15
+#define OPTIONS_BIT15          (0x1 << 15)
+#else
+#define OPTIONS_BIT15          0x0
+#endif
+
+#if defined(SUPPORT_DISPLAYCONTROLLER_TILING) || defined (INTERNAL_TEST)
+#define SUPPORT_DISPLAYCONTROLLER_TILING_SET_OFFSET    OPTIONS_BIT16
+#define OPTIONS_BIT16          (0x1 << 16)
+#else
+#define OPTIONS_BIT16          0x0
+#endif
+
+#if defined(SUPPORT_PERCONTEXT_PB) || defined (INTERNAL_TEST)
+#define SUPPORT_PERCONTEXT_PB_SET_OFFSET       OPTIONS_BIT17
+#define OPTIONS_BIT17          (0x1 << 17)
+#else
+#define OPTIONS_BIT17          0x0
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_HWPERF_SET_OFFSET  OPTIONS_BIT18
+#define OPTIONS_BIT18          (0x1 << 18)
+#else
+#define OPTIONS_BIT18          0x0
+#endif
+
+
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_MMU_DUMMY_PAGE_SET_OFFSET  OPTIONS_BIT19
+#define OPTIONS_BIT19          (0x1 << 19)
+#else
+#define OPTIONS_BIT19          0x0
+#endif
+
+#if defined(SUPPORT_SGX_PRIORITY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING_SET_OFFSET     OPTIONS_BIT20
+#define OPTIONS_BIT20          (0x1 << 20)
+#else
+#define OPTIONS_BIT20          0x0
+#endif
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_LOW_LATENCY_SCHEDULING_SET_OFFSET  OPTIONS_BIT21
+#define OPTIONS_BIT21          (0x1 << 21)
+#else
+#define OPTIONS_BIT21          0x0
+#endif
+
+#if defined(USE_SUPPORT_NO_TA3D_OVERLAP) || defined (INTERNAL_TEST)
+#define USE_SUPPORT_NO_TA3D_OVERLAP_SET_OFFSET OPTIONS_BIT22
+#define OPTIONS_BIT22          (0x1 << 22)
+#else
+#define OPTIONS_BIT22          0x0
+#endif
+
+#define PVR_DISABLE_SECURE_FD_EXPORT_OFFSET    27
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define OPTIONS_HIGHBYTE ((SGX_FEATURE_MP_CORE_COUNT-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET)
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET   28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK             0xFF
+#else
+#define OPTIONS_HIGHBYTE       0x0
+#endif
+
+#define __BIT_MASK(len)                        ((1ULL << (len)) - 1)
+#define OPTION_BIT_MASK(start, len)    \
+               (__BIT_MASK((start) + (len)) & ~__BIT_MASK(start))
+
+/*
+ * The option bits covered by the following mask must match between kernel and
+ * user space. The rest of the bits in the options word are dynamic, that is
+ * libraries built with or without those will be supported by the kernel. In the
+ * future we would like to minimize the set of these options.
+ */
+#define SGX_BUILD_OPTION_MASK          (OPTION_BIT_MASK(0, 22) | \
+                                        OPTION_BIT_MASK(28, 4))
+
+#define SGX_BUILD_OPTIONS      (\
+       OPTIONS_BIT0 |\
+       OPTIONS_BIT1 |\
+       OPTIONS_BIT2 |\
+       OPTIONS_BIT3 |\
+       OPTIONS_BIT4 |\
+       OPTIONS_BIT5 |\
+       OPTIONS_BIT6 |\
+       OPTIONS_BIT8 |\
+       OPTIONS_BIT9 |\
+       OPTIONS_BIT10 |\
+       OPTIONS_BIT11 |\
+       OPTIONS_BIT12 |\
+       OPTIONS_BIT13 |\
+       OPTIONS_BIT14 |\
+       OPTIONS_BIT15 |\
+       OPTIONS_BIT16 |\
+       OPTIONS_BIT17 |\
+       OPTIONS_BIT18 |\
+       OPTIONS_BIT19 |\
+       OPTIONS_BIT20 |\
+       OPTIONS_BIT21 |\
+       OPTIONS_BIT22 |\
+       OPTIONS_HIGHBYTE        )
+
diff --git a/drivers/staging/mrst/pvr/include4/sgxapi_km.h b/drivers/staging/mrst/pvr/include4/sgxapi_km.h
new file mode 100644 (file)
index 0000000..adee6e1
--- /dev/null
@@ -0,0 +1,401 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __SGXAPI_KM_H__
+#define __SGXAPI_KM_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "sgxdefs.h"
+
+#if defined(__linux__) && !defined(USE_CODE)
+       #if defined(__KERNEL__)
+               #include <asm/unistd.h>
+       #else
+               #include <unistd.h>
+       #endif
+#endif
+
+#define SGX_UNDEFINED_HEAP_ID                                  (~0LU)
+#define SGX_GENERAL_HEAP_ID                                            0
+#define SGX_TADATA_HEAP_ID                                             1
+#define SGX_KERNEL_CODE_HEAP_ID                                        2
+#define SGX_KERNEL_DATA_HEAP_ID                                        3
+#define SGX_PIXELSHADER_HEAP_ID                                        4
+#define SGX_VERTEXSHADER_HEAP_ID                               5
+#define SGX_PDSPIXEL_CODEDATA_HEAP_ID                  6
+#define SGX_PDSVERTEX_CODEDATA_HEAP_ID                 7
+#define SGX_SYNCINFO_HEAP_ID                                   8
+#define SGX_3DPARAMETERS_HEAP_ID                               9
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+#define SGX_GENERAL_MAPPING_HEAP_ID                            10
+#endif
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_2D_HEAP_ID                                                 11
+#else
+#if defined(FIX_HW_BRN_26915)
+#define SGX_CGBUFFER_HEAP_ID                                   12
+#endif
+#endif
+#define SGX_MAX_HEAP_ID                                                        13
+
+#if defined(SGX543) || defined(SGX544) || defined(SGX554)
+#define SGX_USE_CODE_SEGMENT_RANGE_BITS                23
+#else
+#define SGX_USE_CODE_SEGMENT_RANGE_BITS                19
+#endif
+
+#define SGX_MAX_TA_STATUS_VALS 32
+#define SGX_MAX_3D_STATUS_VALS 4
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+#define SGX_MAX_TA_DST_SYNCS                   1
+#define SGX_MAX_TA_SRC_SYNCS                   1
+#define SGX_MAX_3D_SRC_SYNCS                   4
+#else
+#define SGX_MAX_SRC_SYNCS                              8
+#define SGX_MAX_DST_SYNCS                              1
+#endif
+
+
+#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+#define        PVRSRV_SGX_HWPERF_NUM_COUNTERS  8
+#else
+#define        PVRSRV_SGX_HWPERF_NUM_COUNTERS  9
+#endif 
+
+#define PVRSRV_SGX_HWPERF_INVALID                                      0x1
+
+#define PVRSRV_SGX_HWPERF_TRANSFER                                     0x2
+#define PVRSRV_SGX_HWPERF_TA                                           0x3
+#define PVRSRV_SGX_HWPERF_3D                                           0x4
+#define PVRSRV_SGX_HWPERF_2D                                           0x5
+#define PVRSRV_SGX_HWPERF_POWER                                                0x6
+#define PVRSRV_SGX_HWPERF_PERIODIC                                     0x7
+
+#define PVRSRV_SGX_HWPERF_MK_EVENT                                     0x101
+#define PVRSRV_SGX_HWPERF_MK_TA                                                0x102
+#define PVRSRV_SGX_HWPERF_MK_3D                                                0x103
+#define PVRSRV_SGX_HWPERF_MK_2D                                                0x104
+
+#define PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT                    28
+#define PVRSRV_SGX_HWPERF_TYPE_OP_MASK                         ((1UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT) - 1)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_START                                (0UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_END                          (1Ul << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_START          (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_END                    (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_START                                (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_END                          (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_START                                (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_END                          (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_START                                (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_END                          (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_POWER_START                     (PVRSRV_SGX_HWPERF_POWER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_POWER_END                       (PVRSRV_SGX_HWPERF_POWER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_PERIODIC                                (PVRSRV_SGX_HWPERF_PERIODIC)
+
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_START          (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_END                    (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_START                     (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_END                       (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_START                     (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_END                       (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_START                     (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_END                       (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_STATUS_OFF                           (0x0)
+#define PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS                (1UL << 0)
+#define PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON           (1UL << 1)
+#define PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON           (1UL << 2)
+#define PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON       (1UL << 3)
+
+#define PVR_FW_VER_MAJOR(x)    (((x) >> 16) & 0xff)
+#define PVR_FW_VER_MINOR(x)    (((x) >> 8) & 0xff)
+#define PVR_FW_VER_BRANCH(x)   ((x) & 0xff)
+
+typedef struct _PVRSRV_SGX_HWPERF_CB_ENTRY_
+{
+       IMG_UINT32      ui32FrameNo;
+       IMG_UINT32      ui32Type;
+       IMG_UINT32      ui32Ordinal;
+       IMG_UINT32      ui32Info;
+       IMG_UINT32      ui32Clocksx16;
+       IMG_UINT32      ui32Counters[SGX_FEATURE_MP_CORE_COUNT][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+} PVRSRV_SGX_HWPERF_CB_ENTRY;
+
+
+typedef struct _CTL_STATUS_
+{
+       IMG_DEV_VIRTADDR        sStatusDevAddr;
+       IMG_UINT32                      ui32StatusValue;
+} CTL_STATUS;
+
+
+typedef enum _SGX_MISC_INFO_REQUEST_
+{
+       SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
+       SGX_MISC_INFO_REQUEST_SGXREV,
+       SGX_MISC_INFO_REQUEST_DRIVER_SGXREV,
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+       SGX_MISC_INFO_REQUEST_MEMREAD,
+       SGX_MISC_INFO_REQUEST_MEMCOPY,
+#endif 
+       SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS,
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+       SGX_MISC_INFO_REQUEST_SET_BREAKPOINT,
+       SGX_MISC_INFO_REQUEST_WAIT_FOR_BREAKPOINT,
+       SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT,
+       SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT,
+#endif 
+       SGX_MISC_INFO_DUMP_DEBUG_INFO,
+       SGX_MISC_INFO_PANIC,
+       SGX_MISC_INFO_REQUEST_SPM,
+       SGX_MISC_INFO_REQUEST_ACTIVEPOWER,
+       SGX_MISC_INFO_REQUEST_LOCKUPS,
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       SGX_MISC_INFO_RESOURCEPROF_SIMPLE,
+       SGX_MISC_INFO_RESOURCEPROF_GLOBAL,
+       SGX_MISC_INFO_RESOURCEPROF_MEM_INFO,
+#endif
+       SGX_MISC_INFO_REQUEST_FORCE_I16                                 =  0x7fff
+} SGX_MISC_INFO_REQUEST;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_FEATURES
+{
+       IMG_UINT32                      ui32CoreRev;    
+       IMG_UINT32                      ui32CoreID;             
+       IMG_UINT32                      ui32DDKVersion; 
+       IMG_UINT32                      ui32DDKBuild;   
+       IMG_UINT32                      ui32CoreIdSW;   
+       IMG_UINT32                      ui32CoreRevSW;  
+       IMG_UINT32                      ui32BuildOptions;       
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+       IMG_UINT32                      ui32DeviceMemValue;             
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+       IMG_DEV_VIRTADDR        sDevVAEDMStatusBuffer;  
+       IMG_PVOID                       pvEDMStatusBuffer;              
+#endif
+} PVRSRV_SGX_MISCINFO_FEATURES;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_LOCKUPS
+{
+       IMG_UINT32                      ui32HostDetectedLockups; 
+       IMG_UINT32                      ui32uKernelDetectedLockups; 
+} PVRSRV_SGX_MISCINFO_LOCKUPS;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_ACTIVEPOWER
+{
+       IMG_UINT32                      ui32NumActivePowerEvents; 
+} PVRSRV_SGX_MISCINFO_ACTIVEPOWER;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_SPM
+{
+       IMG_HANDLE                      hRTDataSet;                             
+       IMG_UINT32                      ui32NumOutOfMemSignals; 
+       IMG_UINT32                      ui32NumSPMRenders;      
+} PVRSRV_SGX_MISCINFO_SPM;
+
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+typedef struct _SGX_BREAKPOINT_INFO
+{
+       
+       IMG_BOOL                                        bBPEnable;
+       
+       IMG_UINT32                                      ui32BPIndex;
+       
+       IMG_UINT32                  ui32DataMasterMask;
+       
+       IMG_DEV_VIRTADDR                        sBPDevVAddr, sBPDevVAddrEnd;
+       
+       IMG_BOOL                    bTrapped;
+       
+       IMG_BOOL                    bRead;
+       
+       IMG_BOOL                    bWrite;
+       
+       IMG_BOOL                    bTrappedBP;
+       
+       IMG_UINT32                  ui32CoreNum;
+       IMG_DEV_VIRTADDR            sTrappedBPDevVAddr;
+       IMG_UINT32                  ui32TrappedBPBurstLength;
+       IMG_BOOL                    bTrappedBPRead;
+       IMG_UINT32                  ui32TrappedBPDataMaster;
+       IMG_UINT32                  ui32TrappedBPTag;
+} SGX_BREAKPOINT_INFO;
+#endif 
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS
+{
+       
+       IMG_UINT32      ui32NewHWPerfStatus;
+       
+       #if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+       
+       IMG_UINT32      aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+       
+       IMG_UINT32      aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+       #else
+       
+       IMG_UINT32      ui32PerfGroup;
+       #endif 
+} PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS;
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+#define MAX_PROC 80
+typedef struct _PVRSRV_SGX_RESOURCE_INFO
+{
+       IMG_UINT32  ui32TotalMem;
+       IMG_UINT32  ui32UsedMem;
+       IMG_UINT32  aui32ProcMem[MAX_PROC][3];
+       IMG_UINT32  ui32ProcCnt;
+} PVRSRV_SGX_RESOURCE_INFO;
+#endif
+
+
+typedef struct _SGX_MISC_INFO_
+{
+       SGX_MISC_INFO_REQUEST   eRequest;       
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+       IMG_DEV_VIRTADDR                        sDevVAddrSrc;           
+       IMG_DEV_VIRTADDR                        sDevVAddrDest;          
+       IMG_HANDLE                                      hDevMemContext;         
+#endif
+       union
+       {
+               IMG_UINT32      reserved;       
+               PVRSRV_SGX_MISCINFO_FEATURES                                            sSGXFeatures;
+               IMG_UINT32                                                                                      ui32SGXClockSpeed;
+               PVRSRV_SGX_MISCINFO_ACTIVEPOWER                                         sActivePower;
+               PVRSRV_SGX_MISCINFO_LOCKUPS                                                     sLockups;
+               PVRSRV_SGX_MISCINFO_SPM                                                         sSPM;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+               SGX_BREAKPOINT_INFO                                                                     sSGXBreakpointInfo;
+#endif
+               PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS                           sSetHWPerfStatus;
+#if defined(PVRSRV_RESOURCE_PROFILING)
+               PVRSRV_SGX_RESOURCE_INFO                sSGXResourceInfo;
+               PVRSRV_CLIENT_MEM_INFO                  sSGXResProfMemInfo;
+#endif
+       } uData;
+} SGX_MISC_INFO;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_MAX_BLT_SRC_SYNCS               3
+#endif
+
+
+#define SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH          256
+
+typedef struct _SGX_KICKTA_DUMPBITMAP_
+{
+       IMG_DEV_VIRTADDR        sDevBaseAddr;
+       IMG_UINT32                      ui32Flags;
+       IMG_UINT32                      ui32Width;
+       IMG_UINT32                      ui32Height;
+       IMG_UINT32                      ui32Stride;
+       IMG_UINT32                      ui32PDUMPFormat;
+       IMG_UINT32                      ui32BytesPP;
+       IMG_CHAR                        pszName[SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH];
+} SGX_KICKTA_DUMPBITMAP, *PSGX_KICKTA_DUMPBITMAP;
+
+#define PVRSRV_SGX_PDUMP_CONTEXT_MAX_BITMAP_ARRAY_SIZE (16)
+
+typedef struct _PVRSRV_SGX_PDUMP_CONTEXT_
+{
+       
+       IMG_UINT32                                              ui32CacheControl;
+
+} PVRSRV_SGX_PDUMP_CONTEXT;
+
+
+typedef struct _SGX_KICKTA_DUMP_ROFF_
+{
+       IMG_HANDLE                      hKernelMemInfo;                                         
+       IMG_UINT32                      uiAllocIndex;                                           
+       IMG_UINT32                      ui32Offset;                                                     
+       IMG_UINT32                      ui32Value;                                                      
+       IMG_PCHAR                       pszName;                                                        
+} SGX_KICKTA_DUMP_ROFF, *PSGX_KICKTA_DUMP_ROFF;
+
+typedef struct _SGX_KICKTA_DUMP_BUFFER_
+{
+       IMG_UINT32                      ui32SpaceUsed;
+       IMG_UINT32                      ui32Start;                                                      
+       IMG_UINT32                      ui32End;                                                        
+       IMG_UINT32                      ui32BufferSize;                                         
+       IMG_UINT32                      ui32BackEndLength;                                      
+       IMG_UINT32                      uiAllocIndex;
+       IMG_HANDLE                      hKernelMemInfo;                                         
+       IMG_PVOID                       pvLinAddr;
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+       IMG_HANDLE                      hCtrlKernelMemInfo;                                     
+       IMG_DEV_VIRTADDR        sCtrlDevVAddr;                                          
+#endif
+       IMG_PCHAR                       pszName;                                                        
+} SGX_KICKTA_DUMP_BUFFER, *PSGX_KICKTA_DUMP_BUFFER;
+
+#ifdef PDUMP
+typedef struct _SGX_KICKTA_PDUMP_
+{
+       
+       PSGX_KICKTA_DUMPBITMAP          psPDumpBitmapArray;
+       IMG_UINT32                                              ui32PDumpBitmapSize;
+
+       
+       PSGX_KICKTA_DUMP_BUFFER psBufferArray;
+       IMG_UINT32                                              ui32BufferArraySize;
+
+       
+       PSGX_KICKTA_DUMP_ROFF           psROffArray;
+       IMG_UINT32                                              ui32ROffArraySize;
+} SGX_KICKTA_PDUMP, *PSGX_KICKTA_PDUMP;
+#endif 
+
+#if defined(TRANSFER_QUEUE)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_MAX_2D_BLIT_CMD_SIZE               26
+#define SGX_MAX_2D_SRC_SYNC_OPS                        3
+#endif
+#define SGX_MAX_TRANSFER_STATUS_VALS   2
+#define SGX_MAX_TRANSFER_SYNC_OPS      5
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/include4/sgxscript.h b/drivers/staging/mrst/pvr/include4/sgxscript.h
new file mode 100644 (file)
index 0000000..fb5efbb
--- /dev/null
@@ -0,0 +1,81 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __SGXSCRIPT_H__
+#define __SGXSCRIPT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define        SGX_MAX_INIT_COMMANDS   64
+#define        SGX_MAX_DEINIT_COMMANDS 16
+
+typedef        enum _SGX_INIT_OPERATION
+{
+       SGX_INIT_OP_ILLEGAL = 0,
+       SGX_INIT_OP_WRITE_HW_REG,
+#if defined(PDUMP)
+       SGX_INIT_OP_PDUMP_HW_REG,
+#endif
+       SGX_INIT_OP_HALT
+} SGX_INIT_OPERATION;
+
+typedef union _SGX_INIT_COMMAND
+{
+       SGX_INIT_OPERATION eOp;
+       struct {
+               SGX_INIT_OPERATION eOp;
+               IMG_UINT32 ui32Offset;
+               IMG_UINT32 ui32Value;
+       } sWriteHWReg;
+#if defined(PDUMP)
+       struct {
+               SGX_INIT_OPERATION eOp;
+               IMG_UINT32 ui32Offset;
+               IMG_UINT32 ui32Value;
+       } sPDumpHWReg;
+#endif
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+       struct {
+               SGX_INIT_OPERATION eOp;
+       } sWorkaroundBRN22997;
+#endif
+} SGX_INIT_COMMAND;
+
+typedef struct _SGX_INIT_SCRIPTS_
+{
+       SGX_INIT_COMMAND asInitCommandsPart1[SGX_MAX_INIT_COMMANDS];
+       SGX_INIT_COMMAND asInitCommandsPart2[SGX_MAX_INIT_COMMANDS];
+       SGX_INIT_COMMAND asDeinitCommands[SGX_MAX_DEINIT_COMMANDS];
+} SGX_INIT_SCRIPTS;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/pvr_debugfs.c b/drivers/staging/mrst/pvr/pvr_debugfs.c
new file mode 100644 (file)
index 0000000..6f527a6
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Intel Corporation
+ * Author: Luc Verhaegen <libv@codethink.co.uk>
+ * Author: Imre Deak <imre.deak@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/vmalloc.h>
+#include <linux/mutex.h>
+
+#include "img_types.h"
+#include "servicesext.h"
+#include "services.h"
+#include "sgxinfokm.h"
+#include "syscommon.h"
+#include "pvr_bridge_km.h"
+#include "sgxutils.h"
+#include "pvr_debugfs.h"
+#include "mmu.h"
+#include "bridged_support.h"
+#include "mm.h"
+#include "pvr_trace_cmd.h"
+
+static struct dentry *pvr_debugfs_dir;
+
+#ifdef CONFIG_PVR_TRACE_CMD
+
+static void *trcmd_str_buf;
+static u8 *trcmd_snapshot;
+static size_t trcmd_snapshot_size;
+static unsigned long trcmd_busy;
+
+static int pvr_dbg_trcmd_open(struct inode *inode, struct file *file)
+{
+       int r;
+
+       if (test_and_set_bit(0, &trcmd_busy))
+               return -EBUSY;
+
+       trcmd_str_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!trcmd_str_buf) {
+               clear_bit(0, &trcmd_busy);
+
+               return -ENOMEM;
+       }
+
+       r = pvr_trcmd_create_snapshot(&trcmd_snapshot, &trcmd_snapshot_size);
+       if (r < 0) {
+               kfree(trcmd_str_buf);
+               clear_bit(0, &trcmd_busy);
+
+               return r;
+       }
+
+       return 0;
+}
+
+static int pvr_dbg_trcmd_release(struct inode *inode, struct file *file)
+{
+       pvr_trcmd_destroy_snapshot(trcmd_snapshot);
+       kfree(trcmd_str_buf);
+       clear_bit(0, &trcmd_busy);
+
+       return 0;
+}
+
+static ssize_t pvr_dbg_trcmd_read(struct file *file, char __user *buffer,
+                                 size_t count, loff_t *ppos)
+{
+       ssize_t ret;
+
+       ret = pvr_trcmd_print(trcmd_str_buf, max_t(size_t, PAGE_SIZE, count),
+                             trcmd_snapshot, trcmd_snapshot_size, ppos);
+       if (copy_to_user(buffer, trcmd_str_buf, ret))
+               return -EFAULT;
+
+       return ret;
+}
+
+static const struct file_operations pvr_dbg_trcmd_fops = {
+       .owner          = THIS_MODULE,
+       .open           = pvr_dbg_trcmd_open,
+       .release        = pvr_dbg_trcmd_release,
+       .read           = pvr_dbg_trcmd_read,
+};
+#endif
+
+int pvr_debugfs_init(void)
+{
+       pvr_debugfs_dir = debugfs_create_dir("pvr", NULL);
+       if (!pvr_debugfs_dir)
+               goto err;
+
+#ifdef CONFIG_PVR_TRACE_CMD
+       if (!debugfs_create_file("command_trace", S_IRUGO, pvr_debugfs_dir,
+                               NULL, &pvr_dbg_trcmd_fops))
+               goto err;
+#endif
+       return 0;
+err:
+       debugfs_remove_recursive(pvr_debugfs_dir);
+       pr_err("pvr: debugfs init failed\n");
+
+       return -ENODEV;
+}
+
+void pvr_debugfs_cleanup(void)
+{
+       debugfs_remove_recursive(pvr_debugfs_dir);
+}
+
diff --git a/drivers/staging/mrst/pvr/pvr_debugfs.h b/drivers/staging/mrst/pvr/pvr_debugfs.h
new file mode 100644 (file)
index 0000000..ce7c0f1
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _PVR_DEBUGFS_H_
+#define _PVR_DEBUGFS_H_ 1
+
+#ifdef CONFIG_DEBUG_FS
+int pvr_debugfs_init(void);
+void pvr_debugfs_cleanup(void);
+#else
+static inline int pvr_debugfs_init(void)
+{
+       return 0;
+}
+static inline void pvr_debugfs_cleanup(void)
+{
+}
+#endif
+
+#endif /* _PVR_DEBUGFS_H_ */
diff --git a/drivers/staging/mrst/pvr/pvr_trace_cmd.c b/drivers/staging/mrst/pvr/pvr_trace_cmd.c
new file mode 100644 (file)
index 0000000..7c2eba2
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Intel Corporation
+ * Author: Imre Deak <imre.deak@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/vmalloc.h>
+
+#include "img_types.h"
+#include "resman.h"
+#include "handle.h"
+#include "pvr_trace_cmd.h"
+#include "perproc.h"
+#include "pvr_bridge_km.h"
+
+/* Need to be log2 size. */
+#define PVR_TBUF_SIZE  (1 << (CONFIG_PVR_TRACE_CMD_BUF_SHIFT + PAGE_SHIFT))
+
+#define PVR_TRCMD_INDENT       3
+
+static struct pvr_trcmd_buf {
+       int             read_idx;
+       int             write_idx;
+       int             pending_idx;    /*
+                                        * the pending_idx ... write_idx area
+                                        * is already allocated but still being
+                                        * written to
+                                        */
+       int             write_pending;  /*
+                                        * number of writers in the above
+                                        * pending area
+                                        */
+       char            data[PVR_TBUF_SIZE];
+} tbuf;
+
+static LIST_HEAD(syn_track_list);
+
+static char tbuf_overflow[1024];
+
+static DEFINE_SPINLOCK(tbuf_lock);     /* protects tbuf and syn_track_list */
+
+struct tbuf_frame {
+       unsigned short size;
+       unsigned short type;
+       unsigned long pid;
+       unsigned long long time;
+       char pname[16];
+};
+
+struct trcmd_desc {
+       const char *name;
+       size_t (*print)(char *dst, size_t dst_size, const void *tbuf);
+};
+
+static size_t prn_syn(const char *name, char *dst, size_t dst_size,
+                     const struct pvr_trcmd_syn *ts)
+{
+       size_t len;
+
+       if (!ts->addr)
+               return 0;
+
+       len =  scnprintf(dst, dst_size, "%*s%s", PVR_TRCMD_INDENT, "", name);
+       len += scnprintf(&dst[len], dst_size - len, " addr:%08lx", ts->addr);
+       len += scnprintf(&dst[len], dst_size - len,
+                        " rop/c:%8lu/%8lu wop/c:%8lu/%8lu\n",
+                        ts->rd_pend, ts->rd_comp, ts->wr_pend, ts->wr_comp);
+
+       return len;
+}
+
+static size_t trcmd_prn_syn(char *dst, size_t dst_size, const void *tbuf)
+{
+       const struct pvr_trcmd_syn *ts = tbuf;
+
+       return prn_syn("syn     ", dst, dst_size, ts);
+}
+
+static size_t trcmd_prn_sgxkick(char *dst, size_t dst_size, const void *tbuf)
+{
+       const struct pvr_trcmd_sgxkick *d = tbuf;
+       size_t len;
+       int i;
+
+       len  = prn_syn("tatq_syn", dst, dst_size, &d->tatq_syn);
+       len += prn_syn("3dtq_syn", &dst[len], dst_size - len, &d->_3dtq_syn);
+       for (i = 0; i < SGX_MAX_SRC_SYNCS; i++) {
+               char sname[10];
+
+               snprintf(sname, sizeof(sname), "src_syn%d", i);
+               len += prn_syn(sname, &dst[len], dst_size - len,
+                              &d->src_syn[i]);
+       }
+       len += prn_syn("dst_syn ", &dst[len], dst_size - len, &d->dst_syn);
+       len += prn_syn("ta3d_syn", &dst[len], dst_size - len, &d->ta3d_syn);
+       len += scnprintf(&dst[len], dst_size - len, "%*sctx  %08lx\n",
+                        PVR_TRCMD_INDENT, "", d->ctx);
+
+       return len;
+}
+
+static size_t trcmd_prn_sgxtfer(char *dst, size_t dst_size, const void *tbuf)
+{
+       const struct pvr_trcmd_sgxtransfer *d = tbuf;
+       size_t len;
+       int i;
+
+       len  = prn_syn("ta_syn  ", dst, dst_size, &d->ta_syn);
+       len += prn_syn("3d_syn  ", &dst[len], dst_size - len, &d->_3d_syn);
+       for (i = 0; i < ARRAY_SIZE(d->src_syn); i++) {
+               char sname[10];
+
+               snprintf(sname, sizeof(sname), "src_syn%d", i);
+               len += prn_syn(sname, &dst[len], dst_size - len,
+                              &d->src_syn[i]);
+       }
+       for (i = 0; i < ARRAY_SIZE(d->dst_syn); i++) {
+               char sname[10];
+
+               snprintf(sname, sizeof(sname), "dst_syn%d", i);
+               len += prn_syn(sname, &dst[len], dst_size - len,
+                              &d->dst_syn[i]);
+       }
+       len += scnprintf(&dst[len], dst_size - len, "%*sctx  %08lx\n",
+                        PVR_TRCMD_INDENT, "", d->ctx);
+
+       return len;
+}
+
+static size_t trcmd_prn_flpreq(char *dst, size_t dst_size, const void *tbuf)
+{
+       const struct pvr_trcmd_flpreq *d = tbuf;
+       size_t len = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(d->src_syn); i++) {
+               char sname[10];
+
+               snprintf(sname, sizeof(sname), "src_syn%d", i);
+               len += prn_syn(sname, &dst[len], dst_size - len,
+                              &d->src_syn[i]);
+       }
+
+       return len;
+}
+
+static struct trcmd_desc trcmd_desc_table[] = {
+       [PVR_TRCMD_SGX_FIRSTKICK]    = { "sgx_first_kick", trcmd_prn_sgxkick },
+       [PVR_TRCMD_SGX_KICK]         = { "sgx_kick", trcmd_prn_sgxkick },
+       [PVR_TRCMD_SGX_TFER_KICK]    = { "sgx_tfer_kick", trcmd_prn_sgxtfer },
+       [PVR_TRCMD_SGX_QBLT_SYNCHK]  = { "sgx_qblt_synchk", trcmd_prn_syn },
+       [PVR_TRCMD_SGX_COMP]         = { "sgx_comp", trcmd_prn_syn },
+       [PVR_TRCMD_FLPREQ]           = { "sgx_flip_req", trcmd_prn_flpreq },
+       [PVR_TRCMD_FLPCOMP]          = { "sgx_flip_comp", trcmd_prn_syn },
+       [PVR_TRCMD_SYN_REMOVE]       = { "sgx_syn_remove", trcmd_prn_syn },
+};
+
+/* Modular add */
+static inline int tbuf_idx_add(int val, int delta)
+{
+       val += delta;
+       val &= PVR_TBUF_SIZE - 1;
+
+       return val;
+}
+
+static size_t prn_frame(const struct tbuf_frame *f, char *dst, size_t dst_size)
+{
+       const struct trcmd_desc *desc;
+       unsigned long long sec;
+       unsigned long usec_frac;
+       size_t len;
+
+       desc = &trcmd_desc_table[f->type];
+
+       sec = f->time;
+       usec_frac = do_div(sec, 1000000000) / 1000;
+
+       len = scnprintf(dst, dst_size, "[%5llu.%06lu] %s[%ld]: %s\n",
+                       sec, usec_frac, f->pname, f->pid, desc->name);
+       if (desc->print)
+               len += desc->print(&dst[len], dst_size - len, (void *)(f + 1));
+
+       return len;
+}
+
+int pvr_trcmd_create_snapshot(uint8_t **snapshot_ret, size_t *snapshot_size)
+{
+       uint8_t *snapshot = NULL;
+       int read_idx;
+       size_t size = -1;
+       size_t tail_size;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tbuf_lock, flags);
+
+       while (1) {
+               int check_size;
+
+               read_idx = tbuf.read_idx;
+               check_size = tbuf_idx_add(tbuf.pending_idx, -read_idx);
+               if (snapshot || !size) {
+                       if (size == check_size)
+                               break;
+                       /* alloc size changed, try again */
+               }
+               size = check_size;
+
+               spin_unlock_irqrestore(&tbuf_lock, flags);
+
+               /*
+                * vmalloc might reschedule, so release the lock and recheck
+                * later if the required allocation size changed. If so, try
+                * again.
+                */
+               if (snapshot)
+                       vfree(snapshot);
+               if (size) {
+                       snapshot = vmalloc(size);
+
+                       if (!snapshot)
+                               return -ENOMEM;
+               }
+
+               spin_lock_irqsave(&tbuf_lock, flags);
+       }
+
+       tail_size = min_t(size_t, size, PVR_TBUF_SIZE - read_idx);
+       memcpy(snapshot, &tbuf.data[read_idx], tail_size);
+       memcpy(&snapshot[tail_size], tbuf.data, size - tail_size);
+
+       spin_unlock_irqrestore(&tbuf_lock, flags);
+
+       *snapshot_ret = snapshot;
+       *snapshot_size = size;
+
+       return 0;
+}
+
+void pvr_trcmd_destroy_snapshot(void *snapshot)
+{
+       vfree(snapshot);
+}
+
+size_t pvr_trcmd_print(char *dst, size_t dst_size, const u8 *snapshot,
+                      size_t snapshot_size, loff_t *snapshot_ofs)
+{
+       size_t dst_len;
+
+       if (*snapshot_ofs >= snapshot_size)
+               return 0;
+       dst_len = 0;
+
+       snapshot_size -= *snapshot_ofs;
+
+       while (snapshot_size) {
+               const struct tbuf_frame *f;
+               size_t this_len;
+
+               if (WARN_ON_ONCE(snapshot_size < 4))
+                       break;
+
+               f = (struct tbuf_frame *)&snapshot[*snapshot_ofs];
+               if (WARN_ON_ONCE(!f->size || f->size > snapshot_size ||
+                                f->type >= ARRAY_SIZE(trcmd_desc_table)))
+                       break;
+
+               if (f->type != PVR_TRCMD_PAD)
+                       this_len = prn_frame(f, &dst[dst_len],
+                                            dst_size - dst_len);
+               else
+                       this_len = 0;
+
+               if (dst_len + this_len + 1 == dst_size) {
+                       /* drop the last printed frame */
+                       dst[dst_len] = '\0';
+
+                       break;
+               }
+
+               *snapshot_ofs += f->size;
+               dst_len += this_len;
+               snapshot_size -= f->size;
+       }
+
+       return dst_len;
+}
+
+static void *tbuf_get_space(size_t size)
+{
+       void *ret;
+       int buf_idx;
+
+       while (1) {
+               if (tbuf_idx_add(tbuf.pending_idx - 1, -tbuf.write_idx) <
+                   size) {
+                       /*
+                        * Can't allocate into the incomplete area, since it
+                        * might be still being written to. New data will be
+                        * lost.
+                        */
+                       WARN_ONCE(1, "pvr: command trace buffer overflow\n");
+
+                       return NULL;
+               }
+
+               if (tbuf_idx_add(tbuf.read_idx - 1, -tbuf.write_idx) < size) {
+                       /*
+                        * Trace buffer overflow, discard the frame that will
+                        * be overwritten by the next write. Old data will be
+                        * lost.
+                        */
+                       struct tbuf_frame *f;
+
+                       f = (struct tbuf_frame *)&tbuf.data[tbuf.read_idx];
+                       buf_idx = tbuf.read_idx;
+                       tbuf.read_idx = tbuf_idx_add(tbuf.read_idx, f->size);
+               } else if (PVR_TBUF_SIZE - tbuf.write_idx < size) {
+                       struct tbuf_frame *f =
+                               (void *)&tbuf.data[tbuf.write_idx];
+                       /*
+                        * Not enough space until the end of trace buffer,
+                        * rewind to the beginning. Frames are sizeof(long)
+                        * aligned, thus we are guaranteed to have space for
+                        * the following two fields.
+                        */
+                       f->size = PVR_TBUF_SIZE - tbuf.write_idx;
+                       f->type = PVR_TRCMD_PAD;
+                       if (tbuf.pending_idx == tbuf.write_idx)
+                               tbuf.pending_idx = 0;
+                       tbuf.write_idx = 0;
+               } else {
+                       break;
+               }
+       }
+       ret = &tbuf.data[tbuf.write_idx];
+       tbuf.write_idx = tbuf_idx_add(tbuf.write_idx, size);
+
+       return ret;
+}
+
+static void *frame_reserve(unsigned type, int pid, const char *pname,
+                          size_t size)
+{
+       struct tbuf_frame *f;
+       size_t total_size;
+
+       size = ALIGN(size, __alignof__(*f));
+       total_size = sizeof(*f) + size;
+       f = tbuf_get_space(total_size);
+       if (!f) {
+               /*
+                * Return something the caller can write into, so the caller
+                * doesn't need to check for NULL.
+                */
+               WARN_ON_ONCE(total_size > sizeof(tbuf_overflow));
+
+               return tbuf_overflow;
+       }
+       tbuf.write_pending++;
+
+       f->size = total_size;
+       f->type = type;
+       f->pid = pid;
+       f->time = cpu_clock(smp_processor_id());
+       strlcpy(f->pname, pname, sizeof(f->pname));
+
+       return f + 1;
+}
+
+static void frame_commit(void *alloc_ptr)
+{
+       struct tbuf_frame *f;
+
+       if (alloc_ptr == tbuf_overflow)
+               return;
+
+       if (WARN_ON_ONCE(tbuf.write_pending <= 0))
+               return;
+
+       f = (struct tbuf_frame *)alloc_ptr - 1;
+
+       tbuf.write_pending--;
+       WARN_ON_ONCE(f->size > tbuf_idx_add(tbuf.write_idx, -tbuf.pending_idx));
+       if (!tbuf.write_pending) {
+               tbuf.pending_idx = tbuf.write_idx;
+       } else {
+               int f_idx = (char *)f - tbuf.data;
+
+               if (f_idx == tbuf.pending_idx)
+                       tbuf.pending_idx = tbuf_idx_add(tbuf.pending_idx,
+                                                       f->size);
+       }
+}
+
+void *pvr_trcmd_reserve(unsigned type, int pid, const char *pname, size_t size)
+{
+       struct tbuf_frame *f;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tbuf_lock, flags);
+       f = frame_reserve(type, pid, pname, size);
+       spin_unlock_irqrestore(&tbuf_lock, flags);
+
+       return f;
+}
+
+void pvr_trcmd_commit(void *alloc_ptr)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&tbuf_lock, flags);
+       frame_commit(alloc_ptr);
+       spin_unlock_irqrestore(&tbuf_lock, flags);
+}
+
+static void add_syn_to_track_list(PVRSRV_KERNEL_SYNC_INFO *si)
+{
+       /* only add if not already on the list */
+       if (list_empty(&si->link))
+               list_add(&si->link, &syn_track_list);
+}
+
+static void remove_syn_from_track_list(PVRSRV_KERNEL_SYNC_INFO *si)
+{
+       list_del_init(&si->link);
+}
+
+static void __set_syn(struct pvr_trcmd_syn *ts,
+                     PVRSRV_KERNEL_SYNC_INFO *si)
+{
+       PVRSRV_SYNC_DATA *sd = si->psSyncData;
+
+       ts->rd_pend = sd->ui32ReadOpsPending;
+       ts->rd_comp = sd->ui32ReadOpsComplete;
+       ts->wr_pend = sd->ui32WriteOpsPending;
+       ts->wr_comp = sd->ui32WriteOpsComplete;
+       ts->addr    = si->sWriteOpsCompleteDevVAddr.uiAddr - 4;
+}
+
+void pvr_trcmd_remove_syn(int pid, const char *pname,
+                         PVRSRV_KERNEL_SYNC_INFO *si)
+{
+       struct pvr_trcmd_syn *ts;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tbuf_lock, flags);
+
+       ts = frame_reserve(PVR_TRCMD_SYN_REMOVE, pid, pname,
+                                sizeof(*ts));
+       __set_syn(ts, si);
+       frame_commit(ts);
+       remove_syn_from_track_list(si);
+
+       spin_unlock_irqrestore(&tbuf_lock, flags);
+}
+
+void pvr_trcmd_set_syn(struct pvr_trcmd_syn *ts,
+                      PVRSRV_KERNEL_SYNC_INFO *si)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&tbuf_lock, flags);
+       add_syn_to_track_list(si);
+       spin_unlock_irqrestore(&tbuf_lock, flags);
+
+       __set_syn(ts, si);
+}
+
+static unsigned long calc_syn_digest(PVRSRV_SYNC_DATA *sd)
+{
+       return sd->ui32ReadOpsPending +
+              sd->ui32ReadOpsComplete +
+              sd->ui32WriteOpsPending +
+              sd->ui32WriteOpsComplete;
+}
+
+static int syn_has_changed(PVRSRV_KERNEL_SYNC_INFO *si)
+{
+       unsigned long digest;
+       int changed;
+
+       digest = calc_syn_digest(si->psSyncData);
+       changed = digest != si->counter_digest;
+       si->counter_digest = digest;
+
+       return changed;
+}
+
+static int syn_is_complete(PVRSRV_KERNEL_SYNC_INFO *si)
+{
+       PVRSRV_SYNC_DATA *sd = si->psSyncData;
+
+       return sd->ui32ReadOpsPending == sd->ui32ReadOpsComplete &&
+              sd->ui32WriteOpsPending == sd->ui32WriteOpsComplete;
+}
+
+void pvr_trcmd_check_syn_completions(int type)
+{
+       PVRSRV_KERNEL_SYNC_INFO *si;
+       PVRSRV_KERNEL_SYNC_INFO *tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tbuf_lock, flags);
+
+       list_for_each_entry_safe(si, tmp, &syn_track_list, link) {
+               if (syn_has_changed(si)) {
+                       struct pvr_trcmd_syn *ts;
+
+                       ts = frame_reserve(type, 0, "irq", sizeof(*ts));
+                       __set_syn(ts, si);
+                       frame_commit(ts);
+               }
+               if (syn_is_complete(si))
+                       remove_syn_from_track_list(si);
+       }
+
+       spin_unlock_irqrestore(&tbuf_lock, flags);
+}
diff --git a/drivers/staging/mrst/pvr/pvr_trace_cmd.h b/drivers/staging/mrst/pvr/pvr_trace_cmd.h
new file mode 100644 (file)
index 0000000..9b7cc6a
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Intel Corporation
+ * Author: Imre Deak <imre.deak@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __PVR_TRACE_CMD_H__
+#define __PVR_TRACE_CMD_H__
+
+#include <linux/mutex.h>
+
+#include "servicesint.h"
+#include "sgxapi_km.h"
+
+enum pvr_trcmd_type {
+       PVR_TRCMD_PAD,
+       PVR_TRCMD_SGX_FIRSTKICK,
+       PVR_TRCMD_SGX_KICK,
+       PVR_TRCMD_SGX_TFER_KICK,
+       PVR_TRCMD_SGX_COMP,
+       PVR_TRCMD_SYN_REMOVE,
+       PVR_TRCMD_SGX_QBLT_SYNCHK,
+       PVR_TRCMD_FLPREQ,
+       PVR_TRCMD_FLPCOMP,
+};
+
+struct pvr_trcmd_buf;
+
+struct pvr_trcmd_syn {
+       unsigned long   rd_pend;
+       unsigned long   rd_comp;
+       unsigned long   wr_pend;
+       unsigned long   wr_comp;
+       unsigned long   addr;
+};
+
+struct pvr_trcmd_sgxkick {
+       struct pvr_trcmd_syn    tatq_syn;
+       struct pvr_trcmd_syn    _3dtq_syn;
+       struct pvr_trcmd_syn    src_syn[SGX_MAX_SRC_SYNCS];
+       struct pvr_trcmd_syn    dst_syn;
+       struct pvr_trcmd_syn    ta3d_syn;
+       unsigned long           ctx;
+};
+
+struct pvr_trcmd_sgxtransfer {
+       struct pvr_trcmd_syn    ta_syn;
+       struct pvr_trcmd_syn    _3d_syn;
+       struct pvr_trcmd_syn    src_syn[SGX_MAX_TRANSFER_SYNC_OPS];
+       struct pvr_trcmd_syn    dst_syn[SGX_MAX_TRANSFER_SYNC_OPS];
+       unsigned long           ctx;
+};
+
+struct pvr_trcmd_flpreq {
+       struct pvr_trcmd_syn    src_syn[2];
+};
+
+#ifdef CONFIG_PVR_TRACE_CMD
+
+void *pvr_trcmd_reserve(unsigned type, int pid, const char *pname,
+                          size_t size);
+
+void pvr_trcmd_commit(void *alloc_ptr);
+
+int pvr_trcmd_create_snapshot(u8 **snapshot_ret, size_t *snapshot_size);
+void pvr_trcmd_destroy_snapshot(void *snapshot);
+
+size_t pvr_trcmd_print(char *dst, size_t dst_size, const u8 *snapshot,
+                      size_t snapshot_size, loff_t *snapshot_ofs);
+
+void pvr_trcmd_set_syn(struct pvr_trcmd_syn *ts,
+                      PVRSRV_KERNEL_SYNC_INFO *si);
+
+void pvr_trcmd_remove_syn(int pid, const char *pname,
+                         PVRSRV_KERNEL_SYNC_INFO *si);
+
+static inline void pvr_trcmd_set_data(unsigned long *a, unsigned long val)
+{
+       *a = val;
+}
+
+static inline void pvr_trcmd_clear_syn(struct pvr_trcmd_syn *ts)
+{
+       memset(ts, 0, sizeof(*ts));
+}
+
+void pvr_trcmd_check_syn_completions(int type);
+
+#else
+
+static inline void *
+pvr_trcmd_reserve(unsigned type, int pid, const char *pname,
+                          size_t size)
+{
+       return NULL;
+}
+
+static inline void pvr_trcmd_commit(void *alloc_ptr)
+{
+}
+
+static inline int
+pvr_trcmd_create_snapshot(u8 **snapshot_ret, size_t *snapshot_size)
+{
+       return 0;
+}
+
+static inline void pvr_trcmd_destroy_snapshot(void *snapshot)
+{
+}
+
+static inline size_t
+pvr_trcmd_print(char *dst, size_t dst_size, const u8 *snapshot,
+               size_t snapshot_size, loff_t *snapshot_ofs)
+{
+       return 0;
+}
+
+static inline void
+pvr_trcmd_set_syn(struct pvr_trcmd_syn *ts,
+                 PVRSRV_KERNEL_SYNC_INFO *si)
+{
+}
+
+static inline void pvr_trcmd_remove_syn(int pid, const char *pname,
+                                       PVRSRV_KERNEL_SYNC_INFO *si)
+{
+}
+
+static inline void pvr_trcmd_set_data(unsigned long *a, unsigned long val)
+{
+}
+
+static inline void pvr_trcmd_clear_syn(struct pvr_trcmd_syn *ts)
+{
+}
+
+static inline void pvr_trcmd_check_syn_completions(int type)
+{
+}
+
+#endif         /* CONFIG_PVR_SYNC_CNT */
+
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/.gitignore b/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/.gitignore
new file mode 100644 (file)
index 0000000..f558f8b
--- /dev/null
@@ -0,0 +1,6 @@
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+binary_pc_i686*
+*.o
+*.o.cmd
diff --git a/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/makefile.linux.common b/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/makefile.linux.common
new file mode 100644 (file)
index 0000000..c3ab6f4
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful but, except
+# as otherwise stated in writing, without any warranty; without even the
+# implied warranty of merchantability or fitness for a particular purpose.
+# See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Contact Information:
+# Imagination Technologies Ltd. <gpl-support@imgtec.com>
+# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+#
+#
+#
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+DISPLAY_CONTROLLER_SOURCES_ROOT = $(KBUILDROOT)/$(DISPLAY_CONTROLLER_DIR)
+else
+DISPLAY_CONTROLLER_SOURCES_ROOT = ..
+endif
+
+INCLUDES +=    -I$(EURASIAROOT)/include4 \
+               -I$(EURASIAROOT)/services4/include \
+               -I$(EURASIAROOT)/services4/system/$(PVR_SYSTEM) \
+               -I$(EURASIAROOT)/services4/system/include \
+               -I$(EURASIAROOT)/services4/srvkm/env/linux/mrst
+
+SOURCES        +=      $(DISPLAY_CONTROLLER_SOURCES_ROOT)/mrstlfb_displayclass.c \
+                       $(DISPLAY_CONTROLLER_SOURCES_ROOT)/mrstlfb_linux.c
+MODULE_CFLAGS += -DPVR_MRST_FB_SET_PAR_ON_INIT
diff --git a/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb.h b/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb.h
new file mode 100644 (file)
index 0000000..b4af6de
--- /dev/null
@@ -0,0 +1,300 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __MRSTLFB_H__
+#define __MRSTLFB_H__
+
+#include <drm/drmP.h>
+#include "psb_intel_reg.h"
+
+#define MRST_USING_INTERRUPTS
+
+#define PSB_HWSTAM                0x2098
+#define PSB_INSTPM                0x20C0
+#define PSB_INT_IDENTITY_R        0x20A4
+#define _PSB_VSYNC_PIPEB_FLAG     (1<<5)
+#define _PSB_VSYNC_PIPEA_FLAG     (1<<7)
+#define _PSB_IRQ_SGX_FLAG         (1<<18)
+#define _PSB_IRQ_MSVDX_FLAG       (1<<19)
+#define _LNC_IRQ_TOPAZ_FLAG       (1<<20)
+#define PSB_INT_MASK_R            0x20A8
+#define PSB_INT_ENABLE_R          0x20A0
+
+#define MAX_SWAPCHAINS                   10
+
+/* IPC message and command defines used to enable/disable mipi panel voltages */
+#define        IPC_MSG_PANEL_ON_OFF    0xE9
+#define IPC_CMD_PANEL_ON       1
+#define IPC_CMD_PANEL_OFF      0
+
+typedef void *   MRST_HANDLE;
+
+typedef enum tag_mrst_bool
+{
+       MRST_FALSE = 0,
+       MRST_TRUE  = 1,
+} MRST_BOOL, *MRST_PBOOL;
+
+typedef int(* MRSTLFB_VSYNC_ISR_PFN)(struct drm_device* psDrmDevice, int iPipe);
+
+
+typedef struct MRSTLFB_BUFFER_TAG
+{
+       
+    IMG_UINT32                         ui32BufferSize;
+       union {
+               
+               IMG_SYS_PHYADDR             *psNonCont;
+               
+               IMG_SYS_PHYADDR                         sCont;
+       } uSysAddr;
+       
+       IMG_DEV_VIRTADDR                sDevVAddr;
+       
+    IMG_CPU_VIRTADDR                   sCPUVAddr;    
+       
+       PVRSRV_SYNC_DATA                *psSyncData;
+       
+       MRST_BOOL                                               bIsContiguous;
+       
+       MRST_BOOL                                               bIsAllocated;
+
+       IMG_UINT32                                              ui32OwnerTaskID;
+} MRSTLFB_BUFFER;
+
+typedef struct MRSTLFB_VSYNC_FLIP_ITEM_TAG
+{
+
+
+
+       MRST_HANDLE      hCmdComplete;
+
+       unsigned long    ulSwapInterval;
+
+       MRST_BOOL        bValid;
+
+       MRST_BOOL        bFlipped;
+
+       MRST_BOOL        bCmdCompleted;
+
+
+
+
+
+       MRSTLFB_BUFFER* psBuffer;
+} MRSTLFB_VSYNC_FLIP_ITEM;
+
+typedef struct MRSTLFB_SWAPCHAIN_TAG
+{
+       
+       unsigned long       ulBufferCount;
+
+       IMG_UINT32                      ui32SwapChainID;
+
+       
+       MRSTLFB_BUFFER     **ppsBuffer;
+
+       
+       unsigned long       ulSwapChainLength;
+
+       
+       MRSTLFB_VSYNC_FLIP_ITEM *psVSyncFlips;
+
+       
+       unsigned long       ulInsertIndex;
+       
+       
+       unsigned long       ulRemoveIndex;
+
+       
+       PVRSRV_DC_DISP2SRV_KMJTABLE     *psPVRJTable;
+
+       
+       struct drm_driver         *psDrmDriver;
+
+       
+       struct drm_device         *psDrmDev;
+
+       struct MRSTLFB_SWAPCHAIN_TAG *psNext;
+
+       struct MRSTLFB_DEVINFO_TAG *psDevInfo;
+
+} MRSTLFB_SWAPCHAIN;
+
+typedef struct MRSTLFB_FBINFO_TAG
+{
+       unsigned long       ulFBSize;
+       unsigned long       ulBufferSize;
+       unsigned long       ulRoundedBufferSize;
+       unsigned long       ulWidth;
+       unsigned long       ulHeight;
+       unsigned long       ulByteStride;
+
+
+
+       IMG_SYS_PHYADDR     sSysAddr;
+       IMG_CPU_VIRTADDR    sCPUVAddr;
+        IMG_DEV_VIRTADDR    sDevVAddr;
+
+
+       PVRSRV_PIXEL_FORMAT ePixelFormat;
+}MRSTLFB_FBINFO;
+
+/**
+ * If DRI is enable then extemding drm_device
+ */
+typedef struct MRSTLFB_DEVINFO_TAG
+{
+       unsigned int           uiDeviceID;
+
+       struct drm_device       *psDrmDevice;
+
+       
+
+       MRSTLFB_BUFFER          sSystemBuffer;
+
+       
+       PVRSRV_DC_DISP2SRV_KMJTABLE     sPVRJTable;
+       
+       
+       PVRSRV_DC_SRV2DISP_KMJTABLE     sDCJTable;
+
+       
+       unsigned long           ulRefCount;
+
+       MRSTLFB_SWAPCHAIN      *psCurrentSwapChain;
+
+       MRSTLFB_SWAPCHAIN      *apsSwapChains[MAX_SWAPCHAINS];
+
+       IMG_UINT32              ui32SwapChainNum;
+
+       
+       void *pvRegs;
+
+       
+       unsigned long ulSetFlushStateRefCount;
+
+       
+       MRST_BOOL           bFlushCommands;
+
+       
+       MRST_BOOL           bBlanked;
+
+       
+       struct fb_info         *psLINFBInfo;
+
+       
+       struct notifier_block   sLINNotifBlock;
+
+       
+       spinlock_t             sSwapChainLock;
+
+       
+
+       
+       IMG_DEV_VIRTADDR        sDisplayDevVAddr;
+
+       DISPLAY_INFO            sDisplayInfo;
+
+       
+       DISPLAY_FORMAT          sDisplayFormat;
+       
+       
+       DISPLAY_DIMS            sDisplayDim;
+
+       IMG_UINT32              ui32MainPipe;
+
+       
+       MRST_BOOL bSuspended;
+
+       
+       MRST_BOOL bLeaveVT;
+
+       
+       unsigned long ulLastFlipAddr;
+
+       
+       MRST_BOOL bLastFlipAddrValid;
+}  MRSTLFB_DEVINFO;
+
+#if 0
+#define        MRSTLFB_PAGE_SIZE 4096
+#define        MRSTLFB_PAGE_MASK (MRSTLFB_PAGE_SIZE - 1)
+#define        MRSTLFB_PAGE_TRUNC (~MRSTLFB_PAGE_MASK)
+
+#define        MRSTLFB_PAGE_ROUNDUP(x) (((x) + MRSTLFB_PAGE_MASK) & MRSTLFB_PAGE_TRUNC)
+#endif
+
+#ifdef DEBUG
+#define        DEBUG_PRINTK(x) printk x
+#else
+#define        DEBUG_PRINTK(x)
+#endif
+
+#define DISPLAY_DEVICE_NAME "PowerVR Moorestown Linux Display Driver"
+#define        DRVNAME "mrstlfb"
+#define        DEVNAME DRVNAME
+#define        DRIVER_PREFIX DRVNAME
+
+typedef enum _MRST_ERROR_
+{
+       MRST_OK                             =  0,
+       MRST_ERROR_GENERIC                  =  1,
+       MRST_ERROR_OUT_OF_MEMORY            =  2,
+       MRST_ERROR_TOO_FEW_BUFFERS          =  3,
+       MRST_ERROR_INVALID_PARAMS           =  4,
+       MRST_ERROR_INIT_FAILURE             =  5,
+       MRST_ERROR_CANT_REGISTER_CALLBACK   =  6,
+       MRST_ERROR_INVALID_DEVICE           =  7,
+       MRST_ERROR_DEVICE_REGISTER_FAILED   =  8
+} MRST_ERROR;
+
+
+#ifndef UNREFERENCED_PARAMETER
+#define        UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+MRST_ERROR MRSTLFBInit(struct drm_device * dev);
+MRST_ERROR MRSTLFBDeinit(void);
+
+MRST_ERROR MRSTLFBAllocBuffer(struct MRSTLFB_DEVINFO_TAG *psDevInfo, IMG_UINT32 ui32Size, MRSTLFB_BUFFER **ppBuffer);
+MRST_ERROR MRSTLFBFreeBuffer(struct MRSTLFB_DEVINFO_TAG *psDevInfo, MRSTLFB_BUFFER **ppBuffer);
+
+void *MRSTLFBAllocKernelMem(unsigned long ulSize);
+void MRSTLFBFreeKernelMem(void *pvMem);
+MRST_ERROR MRSTLFBGetLibFuncAddr(char *szFunctionName, PFN_DC_GET_PVRJTABLE *ppfnFuncTable);
+MRST_ERROR MRSTLFBInstallVSyncISR (MRSTLFB_DEVINFO *psDevInfo, MRSTLFB_VSYNC_ISR_PFN pVsyncHandler);
+MRST_ERROR MRSTLFBUninstallVSyncISR(MRSTLFB_DEVINFO *psDevInfo);
+void MRSTLFBEnableVSyncInterrupt(MRSTLFB_DEVINFO *psDevInfo);
+void MRSTLFBDisableVSyncInterrupt(MRSTLFB_DEVINFO *psDevInfo);
+
+void MRSTLFBFlipToSurface(MRSTLFB_DEVINFO *psDevInfo,  unsigned long uiAddr);
+
+void MRSTLFBSuspend(void);
+void MRSTLFBResume(void);
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb_displayclass.c b/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb_displayclass.c
new file mode 100644 (file)
index 0000000..c2a79a7
--- /dev/null
@@ -0,0 +1,2200 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <asm/intel_scu_ipc.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "mrstlfb.h"
+
+#include "psb_fb.h"
+#include "psb_drv.h"
+#include "psb_powermgmt.h"
+
+#if !defined(SUPPORT_DRI_DRM)
+#error "SUPPORT_DRI_DRM must be set"
+#endif
+
+IMG_UINT32 gui32MRSTDisplayDeviceID;
+
+PVRSRV_ERROR MRSTLFBPrePowerState(IMG_HANDLE            hDevHandle,
+                                 PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                 PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR MRSTLFBPostPowerState(IMG_HANDLE            hDevHandle,
+                                  PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                  PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+struct psbfb_par {
+  struct drm_device *dev;
+  void *psbfb;
+
+  int dpms_state;
+
+  int crtc_count;
+
+  uint32_t crtc_ids[2];
+};
+
+static void *gpvAnchor;
+
+
+#define MRSTLFB_COMMAND_COUNT          1
+
+static PFN_DC_GET_PVRJTABLE pfnGetPVRJTable = 0;
+
+static MRSTLFB_DEVINFO * GetAnchorPtr(void)
+{
+       return (MRSTLFB_DEVINFO *)gpvAnchor;
+}
+
+static void SetAnchorPtr(MRSTLFB_DEVINFO *psDevInfo)
+{
+       gpvAnchor = (void*)psDevInfo;
+}
+
+static void MRSTLFBFlip(MRSTLFB_DEVINFO *psDevInfo, MRSTLFB_BUFFER *psBuffer)
+{
+       unsigned long ulAddr = (unsigned long)psBuffer->sDevVAddr.uiAddr;
+
+       if (!psDevInfo->bSuspended && !psDevInfo->bLeaveVT)
+       {
+               MRSTLFBFlipToSurface(psDevInfo, ulAddr);
+       }
+
+       psDevInfo->ulLastFlipAddr = ulAddr;
+       psDevInfo->bLastFlipAddrValid = MRST_TRUE;
+}
+
+static void MRSTLFBRestoreLastFlip(MRSTLFB_DEVINFO *psDevInfo)
+{
+       if (!psDevInfo->bSuspended && !psDevInfo->bLeaveVT)
+       {
+               if (psDevInfo->bLastFlipAddrValid)
+               {
+                       MRSTLFBFlipToSurface(psDevInfo, psDevInfo->ulLastFlipAddr);
+               }
+       }
+}
+
+static void MRSTLFBClearSavedFlip(MRSTLFB_DEVINFO *psDevInfo)
+{
+       psDevInfo->bLastFlipAddrValid = MRST_FALSE;
+}
+
+static void FlushInternalVSyncQueue(MRSTLFB_SWAPCHAIN *psSwapChain, MRST_BOOL bFlip)
+{
+       MRSTLFB_VSYNC_FLIP_ITEM *psFlipItem;
+       unsigned long            ulMaxIndex;
+       unsigned long            i;
+
+       
+       psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
+       ulMaxIndex = psSwapChain->ulSwapChainLength - 1;
+
+       for(i = 0; i < psSwapChain->ulSwapChainLength; i++)
+       {
+               if (psFlipItem->bValid == MRST_FALSE)
+               {
+                       continue;
+               }
+
+               DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": FlushInternalVSyncQueue: Flushing swap buffer (index %lu)\n", psSwapChain->ulRemoveIndex));
+
+               if(psFlipItem->bFlipped == MRST_FALSE)
+               {
+                       if (bFlip)
+                       {
+                               
+                               MRSTLFBFlip(psSwapChain->psDevInfo, psFlipItem->psBuffer);
+                       }
+               }
+               
+               if(psFlipItem->bCmdCompleted == MRST_FALSE)
+               {
+                       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": FlushInternalVSyncQueue: Calling command complete for swap buffer (index %lu)\n", psSwapChain->ulRemoveIndex));
+
+                       psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete((IMG_HANDLE)psFlipItem->hCmdComplete, MRST_TRUE);
+               }
+
+               
+               psSwapChain->ulRemoveIndex++;
+               
+               if(psSwapChain->ulRemoveIndex > ulMaxIndex)
+               {
+                       psSwapChain->ulRemoveIndex = 0;
+               }
+
+               
+               psFlipItem->bFlipped = MRST_FALSE;
+               psFlipItem->bCmdCompleted = MRST_FALSE;
+               psFlipItem->bValid = MRST_FALSE;
+               
+               
+               psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
+       }
+
+       psSwapChain->ulInsertIndex = 0;
+       psSwapChain->ulRemoveIndex = 0;
+}
+
+static void DRMLFBFlipBuffer(MRSTLFB_DEVINFO *psDevInfo, MRSTLFB_SWAPCHAIN *psSwapChain, MRSTLFB_BUFFER *psBuffer) 
+{
+       if(psSwapChain != NULL) 
+       {
+               if(psDevInfo->psCurrentSwapChain != NULL)
+               {
+                       
+                       if(psDevInfo->psCurrentSwapChain != psSwapChain) 
+                               FlushInternalVSyncQueue(psDevInfo->psCurrentSwapChain, MRST_FALSE);
+               }
+               psDevInfo->psCurrentSwapChain = psSwapChain;
+       }
+
+       
+       MRSTLFBFlip(psDevInfo, psBuffer);
+}
+
+static void SetFlushStateNoLock(MRSTLFB_DEVINFO* psDevInfo,
+                                        MRST_BOOL bFlushState)
+{
+       if (bFlushState)
+       {
+               if (psDevInfo->ulSetFlushStateRefCount == 0)
+               {
+                       psDevInfo->bFlushCommands = MRST_TRUE;
+                       if (psDevInfo->psCurrentSwapChain != NULL)
+                       {
+                               FlushInternalVSyncQueue(psDevInfo->psCurrentSwapChain, MRST_TRUE);
+                       }
+               }
+               psDevInfo->ulSetFlushStateRefCount++;
+       }
+       else
+       {
+               if (psDevInfo->ulSetFlushStateRefCount != 0)
+               {
+                       psDevInfo->ulSetFlushStateRefCount--;
+                       if (psDevInfo->ulSetFlushStateRefCount == 0)
+                       {
+                               psDevInfo->bFlushCommands = MRST_FALSE;
+                       }
+               }
+       }
+}
+
+static IMG_VOID SetFlushState(MRSTLFB_DEVINFO* psDevInfo,
+                                      MRST_BOOL bFlushState)
+{
+       unsigned long ulLockFlags;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       SetFlushStateNoLock(psDevInfo, bFlushState);
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+}
+
+static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
+{
+       MRSTLFB_DEVINFO *psDevInfo = (MRSTLFB_DEVINFO *)hDevice;
+
+       switch (ui32State)
+       {
+               case DC_STATE_FLUSH_COMMANDS:
+                       SetFlushState(psDevInfo, MRST_TRUE);
+                       break;
+               case DC_STATE_NO_FLUSH_COMMANDS:
+                       SetFlushState(psDevInfo, MRST_FALSE);
+                       break;
+               default:
+                       break;
+       }
+
+       return;
+}
+
+static int FrameBufferEvents(struct notifier_block *psNotif,
+                             unsigned long event, void *data)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+       struct fb_event *psFBEvent = (struct fb_event *)data;
+       MRST_BOOL bBlanked;
+
+       
+       if (event != FB_EVENT_BLANK)
+       {
+               return 0;
+       }
+
+       psDevInfo = GetAnchorPtr();
+
+       bBlanked = (*(IMG_INT *)psFBEvent->data != 0) ? MRST_TRUE: MRST_FALSE;
+
+       if (bBlanked != psDevInfo->bBlanked)
+       {
+               psDevInfo->bBlanked = bBlanked;
+
+               SetFlushState(psDevInfo, bBlanked);
+       }
+
+       return 0;
+}
+
+
+static MRST_ERROR UnblankDisplay(MRSTLFB_DEVINFO *psDevInfo)
+{
+       int res;
+
+       console_lock();
+       res = fb_blank(psDevInfo->psLINFBInfo, 0);
+       console_unlock();
+       if (res != 0)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX
+                       ": fb_blank failed (%d)", res);
+               return (MRST_ERROR_GENERIC);
+       }
+
+       return (MRST_OK);
+}
+
+static MRST_ERROR EnableLFBEventNotification(MRSTLFB_DEVINFO *psDevInfo)
+{
+       int                res;
+       MRST_ERROR         eError;
+
+       
+       memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));
+
+       psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;
+       psDevInfo->bBlanked = MRST_FALSE;
+
+       res = fb_register_client(&psDevInfo->sLINNotifBlock);
+       if (res != 0)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX
+                       ": fb_register_client failed (%d)", res);
+
+               return (MRST_ERROR_GENERIC);
+       }
+
+       eError = UnblankDisplay(psDevInfo);
+       if (eError != MRST_OK)
+       {
+               DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+                       ": UnblankDisplay failed (%d)", eError));
+               return eError;
+       }
+
+       return (MRST_OK);
+}
+
+static MRST_ERROR DisableLFBEventNotification(MRSTLFB_DEVINFO *psDevInfo)
+{
+       int res;
+
+
+       res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
+       if (res != 0)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX
+                       ": fb_unregister_client failed (%d)", res);
+               return (MRST_ERROR_GENERIC);
+       }
+
+       return (MRST_OK);
+}
+
+static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 ui32DeviceID,
+                                 IMG_HANDLE *phDevice,
+                                 PVRSRV_SYNC_DATA* psSystemBufferSyncData)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+       MRST_ERROR eError;
+
+       UNREFERENCED_PARAMETER(ui32DeviceID);
+
+       psDevInfo = GetAnchorPtr();
+
+       
+       psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
+
+       psDevInfo->ulSetFlushStateRefCount = 0;
+       psDevInfo->bFlushCommands = MRST_FALSE;
+
+       eError = EnableLFBEventNotification(psDevInfo);
+       if (eError != MRST_OK)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX ": Couldn't enable framebuffer event notification\n");
+               return PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE;
+       }
+
+       
+       *phDevice = (IMG_HANDLE)psDevInfo;
+       
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
+{
+       MRSTLFB_DEVINFO *psDevInfo = (MRSTLFB_DEVINFO *)hDevice;
+       MRST_ERROR eError;
+
+       eError = DisableLFBEventNotification(psDevInfo);
+       if (eError != MRST_OK)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX ": Couldn't disable framebuffer event notification\n");
+               return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+       }
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
+                                  IMG_UINT32 *pui32NumFormats,
+                                  DISPLAY_FORMAT *psFormat)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+
+       if(!hDevice || !pui32NumFormats)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+       *pui32NumFormats = 1;
+
+       if(psFormat)
+       {
+               psFormat[0] = psDevInfo->sDisplayFormat;
+       }
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
+                               DISPLAY_FORMAT *psFormat,
+                               IMG_UINT32 *pui32NumDims,
+                               DISPLAY_DIMS *psDim)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+
+       if(!hDevice || !psFormat || !pui32NumDims)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+       *pui32NumDims = 1;
+
+
+       if(psDim)
+       {
+               psDim[0] = psDevInfo->sDisplayDim;
+       }
+
+       return (PVRSRV_OK);
+}
+
+
+static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+
+       if(!hDevice || !phBuffer)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+       
+       
+       *phBuffer = (IMG_HANDLE)&psDevInfo->sSystemBuffer;
+
+       return (PVRSRV_OK);
+}
+
+
+static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+
+       if(!hDevice || !psDCInfo)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+       *psDCInfo = psDevInfo->sDisplayInfo;
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE        hDevice,
+                                    IMG_HANDLE        hBuffer, 
+                                    IMG_SYS_PHYADDR   **ppsSysAddr,
+                                    IMG_SIZE_T        *pui32ByteSize,
+                                    IMG_VOID          **ppvCpuVAddr,
+                                    IMG_HANDLE        *phOSMapInfo,
+                                    IMG_BOOL          *pbIsContiguous,
+                                   IMG_UINT32        *pui32TilingStride)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+       MRSTLFB_BUFFER *psSystemBuffer;
+
+       UNREFERENCED_PARAMETER(pui32TilingStride);
+
+       if(!hDevice)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+       if(!hBuffer)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+       psSystemBuffer = (MRSTLFB_BUFFER *)hBuffer;
+
+       if (!ppsSysAddr)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       if( psSystemBuffer->bIsContiguous ) 
+               *ppsSysAddr = &psSystemBuffer->uSysAddr.sCont;
+       else
+               *ppsSysAddr = psSystemBuffer->uSysAddr.psNonCont;
+
+       if (!pui32ByteSize)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+       *pui32ByteSize = psSystemBuffer->ui32BufferSize;
+
+       if (ppvCpuVAddr)
+       {
+               *ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
+       }
+
+       if (phOSMapInfo)
+       {
+               *phOSMapInfo = (IMG_HANDLE)0;
+       }
+
+       if (pbIsContiguous)
+       {
+               *pbIsContiguous = psSystemBuffer->bIsContiguous;
+       }
+
+       return (PVRSRV_OK);
+}
+
+
+#if 0
+static MRST_ERROR MRSTLFBEnableSwapChains(MRSTLFB_DEVINFO *psDevInfo) 
+{
+       unsigned long ulLockFlags;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       if(!psDevInfo->bFlushCommands)
+               MRSTLFBEnableVSyncInterrupt(psDevInfo);
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       if (EnableLFBEventNotification(psDevInfo)!= MRST_OK)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX ": Couldn't enable framebuffer event notification\n");
+       }
+
+       return MRST_OK;
+}
+
+static MRST_ERROR MRSTLFBDisableSwapChains(MRSTLFB_DEVINFO *psDevInfo) 
+{
+       MRST_ERROR eError;
+       unsigned long ulLockFlags;
+
+       eError = DisableLFBEventNotification(psDevInfo);
+       if (eError != MRST_OK)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX ": Couldn't disable framebuffer event notification\n");
+       }
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       MRSTLFBDisableVSyncInterrupt(psDevInfo);
+
+       
+       MRSTLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
+
+       psDevInfo->psCurrentSwapChain = NULL;
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+       return MRST_OK;
+}
+#endif
+
+
+static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
+                                      IMG_UINT32 ui32Flags,
+                                      DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+                                      DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+                                      IMG_UINT32 ui32BufferCount,
+                                      PVRSRV_SYNC_DATA **ppsSyncData,
+                                      IMG_UINT32 ui32OEMFlags,
+                                      IMG_HANDLE *phSwapChain,
+                                      IMG_UINT32 *pui32SwapChainID)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+       MRSTLFB_SWAPCHAIN *psSwapChain;
+       MRSTLFB_BUFFER **ppsBuffer;
+       MRSTLFB_VSYNC_FLIP_ITEM *psVSyncFlips;
+       IMG_UINT32 i;
+       IMG_UINT32 iSCId = MAX_SWAPCHAINS;
+       PVRSRV_ERROR eError = PVRSRV_ERROR_NOT_SUPPORTED;
+       unsigned long ulLockFlags;
+       struct drm_device* psDrmDev;
+       unsigned long ulSwapChainLength;
+
+       UNREFERENCED_PARAMETER(ui32OEMFlags);
+       
+       
+       if(!hDevice
+       || !psDstSurfAttrib
+       || !psSrcSurfAttrib
+       || !ppsSyncData
+       || !phSwapChain)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+               
+       
+       if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
+       {
+               return (PVRSRV_ERROR_TOOMANYBUFFERS);
+       }
+       
+       
+       ulSwapChainLength = ui32BufferCount + 1;
+       
+
+       
+       if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat
+       || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride
+       || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width
+       || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height)
+       {
+
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       if(psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat
+       || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride
+       || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width
+       || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height)
+       {
+
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+
+       UNREFERENCED_PARAMETER(ui32Flags);
+
+
+       psSwapChain = (MRSTLFB_SWAPCHAIN*)MRSTLFBAllocKernelMem(sizeof(MRSTLFB_SWAPCHAIN));
+       if(!psSwapChain)
+       {
+               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+       }
+
+       for(iSCId = 0;iSCId < MAX_SWAPCHAINS;++iSCId) 
+       {
+               if( psDevInfo->apsSwapChains[iSCId] == NULL )
+               {
+                       psDevInfo->apsSwapChains[iSCId] = psSwapChain;
+                       break;
+               }
+       }
+
+       if(iSCId == MAX_SWAPCHAINS) 
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorFreeSwapChain;
+       }
+
+       ppsBuffer = (MRSTLFB_BUFFER**)MRSTLFBAllocKernelMem(sizeof(MRSTLFB_BUFFER*) * ui32BufferCount);
+       if(!ppsBuffer)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorFreeSwapChain;
+       }
+
+       psVSyncFlips = (MRSTLFB_VSYNC_FLIP_ITEM *)MRSTLFBAllocKernelMem(sizeof(MRSTLFB_VSYNC_FLIP_ITEM) * ulSwapChainLength);
+       if (!psVSyncFlips)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorFreeBuffers;
+       }
+
+       psSwapChain->ulSwapChainLength = ulSwapChainLength;
+       psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount;
+       psSwapChain->ppsBuffer = ppsBuffer;
+       psSwapChain->psVSyncFlips = psVSyncFlips;
+       psSwapChain->ulInsertIndex = 0;
+       psSwapChain->ulRemoveIndex = 0;
+       psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
+
+       
+       
+       for (i = 0; i < ui32BufferCount; i++)
+       {
+               unsigned long bufSize = psDevInfo->sDisplayDim.ui32ByteStride * psDevInfo->sDisplayDim.ui32Height;
+               MRSTLFBAllocBuffer(psDevInfo, bufSize, &ppsBuffer[i] );
+               ppsBuffer[i]->psSyncData = ppsSyncData[i];              
+       }
+
+       
+       for (i = 0; i < ulSwapChainLength; i++)
+       {
+               psVSyncFlips[i].bValid = MRST_FALSE;
+               psVSyncFlips[i].bFlipped = MRST_FALSE;
+               psVSyncFlips[i].bCmdCompleted = MRST_FALSE;
+       }
+
+
+       psDrmDev = psDevInfo->psDrmDevice;
+
+       psSwapChain->psDevInfo = psDevInfo;
+       psSwapChain->psDrmDev = psDrmDev;
+       psSwapChain->psDrmDriver = psDrmDev->driver;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+   
+       psSwapChain->ui32SwapChainID = *pui32SwapChainID = iSCId+1;
+
+       if(psDevInfo->psCurrentSwapChain == NULL)
+               psDevInfo->psCurrentSwapChain = psSwapChain;
+
+       psDevInfo->ui32SwapChainNum++;
+       if(psDevInfo->ui32SwapChainNum == 1)
+       {
+               MRSTLFBEnableVSyncInterrupt(psDevInfo);
+       }
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       
+       *phSwapChain = (IMG_HANDLE)psSwapChain;
+
+       return (PVRSRV_OK);
+
+       MRSTLFBFreeKernelMem(psVSyncFlips);
+ErrorFreeBuffers:
+       MRSTLFBFreeKernelMem(ppsBuffer);
+ErrorFreeSwapChain:
+       if(iSCId != MAX_SWAPCHAINS && psDevInfo->apsSwapChains[iSCId] == psSwapChain ) 
+               psDevInfo->apsSwapChains[iSCId] = NULL; 
+       MRSTLFBFreeKernelMem(psSwapChain);
+
+       return eError;
+}
+
+static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
+       IMG_HANDLE hSwapChain)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+       MRSTLFB_SWAPCHAIN *psSwapChain;
+       unsigned long ulLockFlags;
+       int i;
+
+       
+       if(!hDevice || !hSwapChain)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+       
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+       psSwapChain = (MRSTLFB_SWAPCHAIN*)hSwapChain;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       psDevInfo->ui32SwapChainNum--;
+
+       if(psDevInfo->ui32SwapChainNum == 0) 
+       {
+               MRSTLFBDisableVSyncInterrupt(psDevInfo);
+               psDevInfo->psCurrentSwapChain = NULL;
+       }
+
+       psDevInfo->apsSwapChains[ psSwapChain->ui32SwapChainID -1] = NULL;
+
+       
+       FlushInternalVSyncQueue(psSwapChain, psDevInfo->ui32SwapChainNum == 0);
+
+       if (psDevInfo->ui32SwapChainNum == 0)
+       {
+               
+               DRMLFBFlipBuffer(psDevInfo, NULL, &psDevInfo->sSystemBuffer);
+               MRSTLFBClearSavedFlip(psDevInfo);
+       }
+
+       if(psDevInfo->psCurrentSwapChain == psSwapChain)
+               psDevInfo->psCurrentSwapChain = NULL;
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       
+       for (i = 0; i < psSwapChain->ulBufferCount; i++)
+       {
+               MRSTLFBFreeBuffer(psDevInfo, &psSwapChain->ppsBuffer[i] );
+       }
+       MRSTLFBFreeKernelMem(psSwapChain->psVSyncFlips);
+       MRSTLFBFreeKernelMem(psSwapChain->ppsBuffer);
+       MRSTLFBFreeKernelMem(psSwapChain);
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
+       IMG_HANDLE hSwapChain,
+       IMG_RECT *psRect)
+{
+       UNREFERENCED_PARAMETER(hDevice);
+       UNREFERENCED_PARAMETER(hSwapChain);
+       UNREFERENCED_PARAMETER(psRect);
+
+
+
+       return (PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
+                                 IMG_HANDLE hSwapChain,
+                                 IMG_RECT *psRect)
+{
+       UNREFERENCED_PARAMETER(hDevice);
+       UNREFERENCED_PARAMETER(hSwapChain);
+       UNREFERENCED_PARAMETER(psRect);
+
+
+
+       return (PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
+                                      IMG_HANDLE hSwapChain,
+                                      IMG_UINT32 ui32CKColour)
+{
+       UNREFERENCED_PARAMETER(hDevice);
+       UNREFERENCED_PARAMETER(hSwapChain);
+       UNREFERENCED_PARAMETER(ui32CKColour);
+
+
+
+       return (PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
+                                      IMG_HANDLE hSwapChain,
+                                      IMG_UINT32 ui32CKColour)
+{
+       UNREFERENCED_PARAMETER(hDevice);
+       UNREFERENCED_PARAMETER(hSwapChain);
+       UNREFERENCED_PARAMETER(ui32CKColour);
+
+
+
+       return (PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
+                                 IMG_HANDLE hSwapChain,
+                                 IMG_UINT32 *pui32BufferCount,
+                                 IMG_HANDLE *phBuffer)
+{
+       MRSTLFB_DEVINFO   *psDevInfo;
+       MRSTLFB_SWAPCHAIN *psSwapChain;
+       unsigned long      i;
+
+
+       if(!hDevice
+       || !hSwapChain
+       || !pui32BufferCount
+       || !phBuffer)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+       psSwapChain = (MRSTLFB_SWAPCHAIN*)hSwapChain;
+
+
+       *pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount;
+
+
+       for(i=0; i<psSwapChain->ulBufferCount; i++)
+       {
+               phBuffer[i] = (IMG_HANDLE)psSwapChain->ppsBuffer[i];
+       }
+       
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
+                                   IMG_HANDLE hBuffer,
+                                   IMG_UINT32 ui32SwapInterval,
+                                   IMG_HANDLE hPrivateTag,
+                                   IMG_UINT32 ui32ClipRectCount,
+                                   IMG_RECT *psClipRect)
+{
+       MRSTLFB_DEVINFO *psDevInfo;
+
+       UNREFERENCED_PARAMETER(ui32SwapInterval);
+       UNREFERENCED_PARAMETER(hPrivateTag);
+       UNREFERENCED_PARAMETER(psClipRect);
+
+       if(!hDevice
+       || !hBuffer
+       || (ui32ClipRectCount != 0))
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice,
+                                   IMG_HANDLE hSwapChain)
+{
+       if(!hDevice || !hSwapChain)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       
+       return (PVRSRV_OK);
+}
+
+static MRST_BOOL MRSTLFBVSyncIHandler(MRSTLFB_DEVINFO *psDevInfo)
+{
+       MRST_BOOL bStatus = MRST_TRUE;
+       MRSTLFB_VSYNC_FLIP_ITEM *psFlipItem;
+       unsigned long ulMaxIndex;
+       unsigned long ulLockFlags;
+       MRSTLFB_SWAPCHAIN *psSwapChain;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       
+       psSwapChain = psDevInfo->psCurrentSwapChain;
+       if (psSwapChain == NULL)
+       {
+               goto ExitUnlock;
+       }
+
+       
+       if (psDevInfo->bFlushCommands || psDevInfo->bSuspended || psDevInfo->bLeaveVT)
+       {
+               goto ExitUnlock;
+       }
+
+       psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
+       ulMaxIndex = psSwapChain->ulSwapChainLength - 1;
+
+       while(psFlipItem->bValid)
+       {       
+               
+               if(psFlipItem->bFlipped)
+               {
+                       
+                       if(!psFlipItem->bCmdCompleted)
+                       {
+                               
+                               MRST_BOOL bScheduleMISR;
+                               
+                               bScheduleMISR = MRST_TRUE;
+
+                               
+                               psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete((IMG_HANDLE)psFlipItem->hCmdComplete, bScheduleMISR);
+
+                               
+                               psFlipItem->bCmdCompleted = MRST_TRUE;
+                       }
+
+                       
+                       /* DGA: fix wrap bug with unsigned int */
+                       if (psFlipItem->ulSwapInterval-- <= 1)
+                       {       
+                               
+                               psSwapChain->ulRemoveIndex++;
+                               
+                               if(psSwapChain->ulRemoveIndex > ulMaxIndex)
+                               {
+                                       psSwapChain->ulRemoveIndex = 0;
+                               }
+                               
+                               
+                               psFlipItem->bCmdCompleted = MRST_FALSE;
+                               psFlipItem->bFlipped = MRST_FALSE;
+       
+                               
+                               psFlipItem->bValid = MRST_FALSE;
+                       }
+                       else
+                       {
+                               
+                               break;
+                       }
+               }
+               else
+               {
+                       
+                       DRMLFBFlipBuffer(psDevInfo, psSwapChain, psFlipItem->psBuffer);
+                       
+                       
+                       psFlipItem->bFlipped = MRST_TRUE;
+                       
+                       
+                       break;
+               }
+               
+               
+               psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
+       }
+               
+ExitUnlock:
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       return bStatus;
+}
+
+#if defined(MRST_USING_INTERRUPTS)
+static int
+MRSTLFBVSyncISR(struct drm_device *psDrmDevice, int iPipe)
+{
+       MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();    
+       struct drm_psb_private *dev_priv =
+                       (struct drm_psb_private *)psDrmDevice->dev_private;
+
+       /* DGA: lets update the DRM device structure's swapchain flag */
+       dev_priv->swap_chain_flag = (int)psDevInfo->psCurrentSwapChain;
+       MRSTLFBVSyncIHandler(psDevInfo);
+
+       
+       return 0;
+}
+#endif
+
+#if 0 /* defined(MRST_USING_INTERRUPTS) */
+static IMG_BOOL
+MRSTLFBISRHandler(IMG_VOID* pvDevInfo)
+{
+        MRSTLFB_DEVINFO *psDevInfo = (MRSTLFB_DEVINFO *)pvDevInfo;
+#if 0
+#ifdef MRST_USING_INTERRUPTS
+       MRSTLFB_SWAPCHAIN *psSwapChain;
+#endif
+#endif
+       unsigned long vdc_stat;
+       struct drm_psb_private *dev_priv;
+#if defined(SUPPORT_DRI_DRM)
+       uint32_t pipea_stat = 0;
+#endif
+
+        if (!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+                DRM_ERROR("ERROR: interrupt arrived but Display HW is power off\n");
+                return IMG_FALSE;
+        }
+       
+#if defined(SUPPORT_DRI_DRM)
+       dev_priv = (struct drm_psb_private *) psDevInfo->psDrmDevice->dev_private;
+
+       pipea_stat = PSB_RVDC32(PIPEASTAT);
+       //write back to clear all interrupt status bits and reset interrupts.
+       PSB_WVDC32(pipea_stat, PIPEASTAT);
+       
+       vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+       vdc_stat &= dev_priv->vdc_irq_mask;
+       if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
+       {
+               drm_handle_vblank(psDevInfo->psDrmDevice, 0);
+       }
+#endif
+
+/* Use drm_handle_vblank() as the VSync handler, otherwise kernel would panic if handle 
+ * the VSync event again. */
+#if 0
+#ifdef MRST_USING_INTERRUPTS
+
+       psSwapChain = psDevInfo->psSwapChain;
+       vdc_stat = MRSTLFBVSyncReadReg(psDevInfo, PSB_INT_IDENTITY_R);
+
+       if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
+       {
+               if(!psDevInfo->psSwapChain)
+               {
+                       psSwapChain = psDevInfo->psSwapChain;
+                       (void) MRSTLFBVSyncIHandler(psSwapChain);
+               }
+       }
+#endif
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+       vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+       vdc_stat &= dev_priv->vdc_irq_mask;
+       if (vdc_stat & _PSB_DPST_PIPEA_FLAG) {
+
+               /* Check for DPST related interrupts */
+               if((pipea_stat & PIPE_DPST_EVENT_STATUS) &&
+                  (dev_priv->psb_dpst_state != NULL)) {
+                       uint32_t pwm_reg = 0;
+                       uint32_t hist_reg = 0;
+                       u32 irqCtrl = 0;
+                       struct dpst_guardband guardband_reg;
+                       struct dpst_ie_histogram_control ie_hist_cont_reg;
+
+                       hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+                       /* Determine if this is histogram or pwm interrupt */
+                       if(hist_reg & HISTOGRAM_INT_CTRL_CLEAR) {
+                               /* Notify UM of histogram interrupt */
+                               psb_dpst_notify_change_um(DPST_EVENT_HIST_INTERRUPT,
+                               dev_priv->psb_dpst_state);
+
+                               /* disable dpst interrupts */
+                               guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+                               guardband_reg.interrupt_enable = 0;
+                               guardband_reg.interrupt_status = 1;
+                               PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
+
+                               ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+                               ie_hist_cont_reg.ie_histogram_enable = 0;
+                               PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
+
+                               irqCtrl = PSB_RVDC32(PIPEASTAT);
+                               irqCtrl &= ~PIPE_DPST_EVENT_ENABLE;
+                               PSB_WVDC32(irqCtrl, PIPEASTAT);
+                       }
+                       pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+                       if((pwm_reg & PWM_PHASEIN_INT_ENABLE) &&
+                          !(pwm_reg & PWM_PHASEIN_ENABLE)) {
+                               /* Notify UM of the phase complete */
+                               psb_dpst_notify_change_um(DPST_EVENT_PHASE_COMPLETE,
+                               dev_priv->psb_dpst_state);
+
+                               /* Temporarily get phase mngr ready to generate
+                                * another interrupt until this can be moved to
+                                * user mode */
+                               /* PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
+                                          PWM_CONTROL_LOGIC); */
+                       }
+               }
+       }
+#endif
+       return IMG_TRUE;
+}
+#endif
+
+static IMG_BOOL ProcessFlip(IMG_HANDLE  hCmdCookie,
+                            IMG_UINT32  ui32DataSize,
+                            IMG_VOID   *pvData)
+{
+       DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+       MRSTLFB_DEVINFO *psDevInfo;
+       MRSTLFB_BUFFER *psBuffer;
+       MRSTLFB_SWAPCHAIN *psSwapChain;
+#if defined(MRST_USING_INTERRUPTS)
+       MRSTLFB_VSYNC_FLIP_ITEM* psFlipItem;
+#endif
+       unsigned long ulLockFlags;
+
+
+       if(!hCmdCookie || !pvData)
+       {
+               return IMG_FALSE;
+       }
+
+
+       psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
+
+       if (psFlipCmd == IMG_NULL || sizeof(DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
+       {
+               return IMG_FALSE;
+       }
+
+
+       psDevInfo = (MRSTLFB_DEVINFO*)psFlipCmd->hExtDevice;
+
+       psBuffer = (MRSTLFB_BUFFER*)psFlipCmd->hExtBuffer;
+       psSwapChain = (MRSTLFB_SWAPCHAIN*) psFlipCmd->hExtSwapChain;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+#if defined(MRST_USING_INTERRUPTS)
+       
+       if(psFlipCmd->ui32SwapInterval == 0 || psDevInfo->bFlushCommands)
+       {
+#endif
+               DRMLFBFlipBuffer(psDevInfo, psSwapChain, psBuffer);
+
+               
+       
+               psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, IMG_TRUE);
+
+#if defined(MRST_USING_INTERRUPTS)
+               goto ExitTrueUnlock;
+       }
+
+       psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulInsertIndex];
+
+       
+       if(psFlipItem->bValid == MRST_FALSE)
+       {
+               unsigned long ulMaxIndex = psSwapChain->ulSwapChainLength - 1;
+               
+               if(psSwapChain->ulInsertIndex == psSwapChain->ulRemoveIndex)
+               {
+                       
+                       DRMLFBFlipBuffer(psDevInfo, psSwapChain, psBuffer);
+
+                       psFlipItem->bFlipped = MRST_TRUE;
+               }
+               else
+               {
+                       psFlipItem->bFlipped = MRST_FALSE;
+               }
+
+               psFlipItem->hCmdComplete = (MRST_HANDLE)hCmdCookie;
+               psFlipItem->ulSwapInterval = (unsigned long)psFlipCmd->ui32SwapInterval;
+               psFlipItem->psBuffer = psBuffer;
+               psFlipItem->bValid = MRST_TRUE;
+
+               psSwapChain->ulInsertIndex++;
+               if(psSwapChain->ulInsertIndex > ulMaxIndex)
+               {
+                       psSwapChain->ulInsertIndex = 0;
+               }
+
+               goto ExitTrueUnlock;
+       }
+       
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+       return IMG_FALSE;
+
+ExitTrueUnlock:
+#endif
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+       return IMG_TRUE;
+}
+
+
+#if defined(PVR_MRST_FB_SET_PAR_ON_INIT)
+static void MRSTFBSetPar(struct fb_info *psLINFBInfo)
+{
+       console_lock();
+
+       if (psLINFBInfo->fbops->fb_set_par != NULL)
+       {
+               int res;
+
+               res = psLINFBInfo->fbops->fb_set_par(psLINFBInfo);
+               if (res != 0)
+               {
+                       printk(KERN_WARNING DRIVER_PREFIX
+                               ": fb_set_par failed: %d\n", res);
+
+               }
+       }
+       else
+       {
+               printk(KERN_WARNING DRIVER_PREFIX
+                       ": fb_set_par not set - HW cursor may not work\n");
+       }
+
+       console_unlock();
+}
+#endif
+
+void MRSTLFBSuspend(void)
+{
+       MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       unsigned long ulLockFlags;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       if (!psDevInfo->bSuspended)
+       {
+#if !defined(PVR_MRST_STYLE_PM)
+               if(psDevInfo->ui32SwapChainNum != 0)
+               {
+                       MRSTLFBDisableVSyncInterrupt(psDevInfo);
+               }
+#endif
+               psDevInfo->bSuspended = MRST_TRUE;
+       }
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+}
+
+void MRSTLFBResume(void)
+{
+       MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       unsigned long ulLockFlags;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       if (psDevInfo->bSuspended)
+       {
+#if !defined(PVR_MRST_STYLE_PM)
+               if(psDevInfo->ui32SwapChainNum != 0)
+               {
+                       MRSTLFBEnableVSyncInterrupt(psDevInfo);
+               }
+#endif
+               psDevInfo->bSuspended = MRST_FALSE;
+
+               MRSTLFBRestoreLastFlip(psDevInfo);
+       }
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+#if !defined(PVR_MRST_STYLE_PM)
+       (void) UnblankDisplay(psDevInfo);
+#endif
+}
+
+#ifdef DRM_PVR_USE_INTEL_FB
+#include "mm.h"
+int MRSTLFBHandleChangeFB(struct drm_device* dev, struct psb_framebuffer *psbfb)
+{
+       MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       int i;
+       struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt * pg = dev_priv->pg;
+       LinuxMemArea *psLinuxMemArea;
+
+       if( !psDevInfo->sSystemBuffer.bIsContiguous )
+               MRSTLFBFreeKernelMem( psDevInfo->sSystemBuffer.uSysAddr.psNonCont );
+
+       psDevInfo->sDisplayFormat.pixelformat = (psbfb->base.depth == 16) ? PVRSRV_PIXEL_FORMAT_RGB565 : PVRSRV_PIXEL_FORMAT_ARGB8888;
+
+       psDevInfo->sDisplayDim.ui32ByteStride = psbfb->base.pitch;
+       psDevInfo->sDisplayDim.ui32Width = psbfb->base.width;
+       psDevInfo->sDisplayDim.ui32Height = psbfb->base.height;
+
+       psDevInfo->sSystemBuffer.ui32BufferSize = psbfb->size;
+
+       if (psbfb->pvrBO != NULL)
+       {
+               psDevInfo->sSystemBuffer.sCPUVAddr = psbfb->fbdev->screen_base;
+               psDevInfo->sSystemBuffer.sDevVAddr.uiAddr = psbfb->offset;
+       }
+       else
+       {
+               psDevInfo->sSystemBuffer.sCPUVAddr = pg->vram_addr;
+               psDevInfo->sSystemBuffer.sDevVAddr.uiAddr = 0;
+       }
+
+       psDevInfo->sSystemBuffer.bIsAllocated = MRST_FALSE;     
+
+       if (psbfb->pvrBO != NULL)
+       {
+               psLinuxMemArea = (LinuxMemArea *)psbfb->pvrBO->sMemBlk.hOSMemHandle;
+       }
+
+       if ((psbfb->pvrBO == NULL) || (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES))
+       {
+               psDevInfo->sSystemBuffer.bIsContiguous = MRST_TRUE;
+               psDevInfo->sSystemBuffer.uSysAddr.sCont.uiAddr = pg->stolen_base;
+       } else {
+               struct page **page_list = psLinuxMemArea->uData.sPageList.pvPageList;
+
+               psDevInfo->sSystemBuffer.bIsContiguous = MRST_FALSE;
+               psDevInfo->sSystemBuffer.uSysAddr.psNonCont = MRSTLFBAllocKernelMem( sizeof( IMG_SYS_PHYADDR ) * (psbfb->size >> PAGE_SHIFT));  
+
+               for (i = 0; i < psbfb->size >> PAGE_SHIFT; i++) 
+               {
+                       psDevInfo->sSystemBuffer.uSysAddr.psNonCont[i].uiAddr = page_to_pfn( page_list[i] ) << PAGE_SHIFT;
+               }
+       } 
+
+       return 0;
+}
+
+#else
+
+int MRSTLFBHandleChangeFB(struct drm_device* dev, struct psb_framebuffer *psbfb)
+{
+       MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       int i;
+       struct drm_psb_private * dev_priv;
+       struct psb_gtt * pg;
+       
+       if( !psDevInfo->sSystemBuffer.bIsContiguous )
+               MRSTLFBFreeKernelMem( psDevInfo->sSystemBuffer.uSysAddr.psNonCont );
+       
+       dev_priv = (struct drm_psb_private *)dev->dev_private;
+       pg = dev_priv->pg;
+
+       psDevInfo->sDisplayFormat.pixelformat = (psbfb->base.depth == 16) ? PVRSRV_PIXEL_FORMAT_RGB565 : PVRSRV_PIXEL_FORMAT_ARGB8888;
+
+       psDevInfo->sDisplayDim.ui32ByteStride = psbfb->base.pitch;
+       psDevInfo->sDisplayDim.ui32Width = psbfb->base.width;
+       psDevInfo->sDisplayDim.ui32Height = psbfb->base.height;
+
+       psDevInfo->sSystemBuffer.ui32BufferSize = psbfb->size;
+       //psDevInfo->sSystemBuffer.sCPUVAddr = psbfb->pvKMAddr;
+       psDevInfo->sSystemBuffer.sCPUVAddr = pg->vram_addr;
+       //psDevInfo->sSystemBuffer.sDevVAddr.uiAddr = psbfb->offsetGTT;
+       psDevInfo->sSystemBuffer.sDevVAddr.uiAddr = 0;
+       psDevInfo->sSystemBuffer.bIsAllocated = IMG_FALSE;      
+
+       if(psbfb->bo ) 
+       {
+               
+               psDevInfo->sSystemBuffer.bIsContiguous = IMG_FALSE;
+               psDevInfo->sSystemBuffer.uSysAddr.psNonCont = MRSTLFBAllocKernelMem( sizeof( IMG_SYS_PHYADDR ) * psbfb->bo->ttm->num_pages);    
+               for(i = 0;i < psbfb->bo->ttm->num_pages;++i) 
+               {
+                       /* struct page *p = ttm_tt_get_page( psbfb->bo->ttm, i);
+
+                       psDevInfo->sSystemBuffer.uSysAddr.psNonCont[i].uiAddr = page_to_pfn(p) << PAGE_SHIFT;   
+                       */
+               }
+       } 
+       else 
+       {
+               
+               //struct drm_device * psDrmDevice = psDevInfo->psDrmDevice;     
+               //struct drm_psb_private * dev_priv = (struct drm_psb_private *)psDrmDevice->dev_private;
+               //struct psb_gtt * pg = dev_priv->pg;
+
+               psDevInfo->sSystemBuffer.bIsContiguous = IMG_TRUE;
+               psDevInfo->sSystemBuffer.uSysAddr.sCont.uiAddr = pg->stolen_base;
+       }
+
+       return 0;
+}
+#endif
+
+static int MRSTLFBFindMainPipe(struct drm_device *dev)  
+{
+       struct drm_crtc *crtc;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)  
+       {
+               if ( drm_helper_crtc_in_use(crtc) ) 
+               {
+                       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+                       return psb_intel_crtc->pipe;
+               }
+       }       
+       
+       return 0;
+}
+
+#if 0
+static int DRMLFBLeaveVTHandler(struct drm_device *dev)  
+{
+       MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       unsigned long ulLockFlags;
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       if (!psDevInfo->bLeaveVT)
+       {
+               if(psDevInfo->psCurrentSwapChain != NULL)
+               {
+                       FlushInternalVSyncQueue(psDevInfo->psCurrentSwapChain, MRST_TRUE);
+                       SetFlushStateNoLock(psDevInfo, MRST_TRUE);
+               }
+
+               DRMLFBFlipBuffer(psDevInfo, NULL, &psDevInfo->sSystemBuffer);
+
+               psDevInfo->bLeaveVT = MRST_TRUE;
+       }
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       return 0;
+}
+
+static int DRMLFBEnterVTHandler(struct drm_device *dev)  
+{
+       MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       unsigned long ulLockFlags;
+
+       spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       if (psDevInfo->bLeaveVT)
+       {
+               if(psDevInfo->psCurrentSwapChain != NULL)
+               {
+                       SetFlushStateNoLock(psDevInfo, MRST_FALSE);
+               }
+
+               psDevInfo->bLeaveVT = MRST_FALSE;
+
+               MRSTLFBRestoreLastFlip(psDevInfo);
+       }
+
+       spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+       return 0;
+}
+#endif
+
+static MRST_ERROR InitDev(MRSTLFB_DEVINFO *psDevInfo)
+{
+       MRST_ERROR eError = MRST_ERROR_GENERIC;
+       struct fb_info *psLINFBInfo;
+       struct drm_device * psDrmDevice = psDevInfo->psDrmDevice;
+       struct drm_psb_private * psDrmPrivate = (struct drm_psb_private *)psDrmDevice->dev_private;
+       struct psb_fbdev * psPsbFBDev = (struct psb_fbdev *)psDrmPrivate->fbdev;
+       struct drm_framebuffer * psDrmFB;
+       struct psb_framebuffer *psbfb;
+       
+
+       int hdisplay;
+       int vdisplay;
+       int i;
+       unsigned long FBSize;
+
+       psDrmFB = psPsbFBDev->psb_fb_helper.fb;
+       if(!psDrmFB) {
+               printk(KERN_INFO"%s:Cannot find drm FB", __FUNCTION__);
+               return eError;
+       }
+       psbfb = to_psb_fb(psDrmFB);
+
+       hdisplay = psDrmFB->width;
+       vdisplay = psDrmFB->height;
+       FBSize = psDrmFB->pitch * psDrmFB->height;
+
+       psLINFBInfo = (struct fb_info*)psPsbFBDev->psb_fb_helper.fbdev;
+
+#if defined(PVR_MRST_FB_SET_PAR_ON_INIT)
+       MRSTFBSetPar(psLINFBInfo);
+#endif
+
+       
+       psDevInfo->sSystemBuffer.bIsContiguous = MRST_TRUE;
+       psDevInfo->sSystemBuffer.bIsAllocated = MRST_FALSE;
+
+       MRSTLFBHandleChangeFB(psDrmDevice, psbfb);
+
+    
+       psDevInfo->sDisplayFormat.pixelformat = PVRSRV_PIXEL_FORMAT_ARGB8888;
+       psDevInfo->psLINFBInfo = psLINFBInfo;
+
+
+       psDevInfo->ui32MainPipe = MRSTLFBFindMainPipe(psDevInfo->psDrmDevice);
+       
+       for(i = 0;i < MAX_SWAPCHAINS;++i) 
+       {
+               psDevInfo->apsSwapChains[i] = NULL;
+       }
+
+       
+       
+       
+       psDevInfo->pvRegs = psbfb_vdc_reg(psDevInfo->psDrmDevice);
+
+       if (psDevInfo->pvRegs == NULL)
+       {
+               eError = PVRSRV_ERROR_BAD_MAPPING;
+               printk(KERN_WARNING DRIVER_PREFIX ": Couldn't map registers needed for flipping\n");
+               return eError;
+       }
+
+       return MRST_OK;
+}
+
+static void DeInitDev(MRSTLFB_DEVINFO *psDevInfo)
+{
+
+}
+
+MRST_ERROR MRSTLFBInit(struct drm_device * dev)
+{
+       MRSTLFB_DEVINFO         *psDevInfo;
+       //struct drm_psb_private *psDrmPriv = (struct drm_psb_private *)dev->dev_private;
+
+       psDevInfo = GetAnchorPtr();
+
+       if (psDevInfo == NULL)
+       {
+               PFN_CMD_PROC                    pfnCmdProcList[MRSTLFB_COMMAND_COUNT];
+               IMG_UINT32                              aui32SyncCountList[MRSTLFB_COMMAND_COUNT][2];
+
+               psDevInfo = (MRSTLFB_DEVINFO *)MRSTLFBAllocKernelMem(sizeof(MRSTLFB_DEVINFO));
+
+               if(!psDevInfo)
+               {
+                       return (MRST_ERROR_OUT_OF_MEMORY);
+               }
+
+
+               memset(psDevInfo, 0, sizeof(MRSTLFB_DEVINFO));
+
+
+               SetAnchorPtr((void*)psDevInfo);
+
+               psDevInfo->psDrmDevice = dev;
+               psDevInfo->ulRefCount = 0;
+
+
+               if(InitDev(psDevInfo) != MRST_OK)
+               {
+                       return (MRST_ERROR_INIT_FAILURE);
+               }
+
+               if(MRSTLFBGetLibFuncAddr ("PVRGetDisplayClassJTable", &pfnGetPVRJTable) != MRST_OK)
+               {
+                       return (MRST_ERROR_INIT_FAILURE);
+               }
+
+
+               if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable))
+               {
+                       return (MRST_ERROR_INIT_FAILURE);
+               }
+
+
+               spin_lock_init(&psDevInfo->sSwapChainLock);
+
+               psDevInfo->psCurrentSwapChain = NULL;
+               psDevInfo->bFlushCommands = MRST_FALSE;
+
+               psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 3;
+               psDevInfo->sDisplayInfo.ui32MaxSwapChains = MAX_SWAPCHAINS;
+               psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
+               psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;
+
+               strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
+       
+
+               DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                       ": Maximum number of swap chain buffers: %u\n",
+                       psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
+
+
+               
+
+               psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
+               psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
+               psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
+               psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
+               psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
+               psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
+               psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
+               psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
+               psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
+               psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
+               psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
+               psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
+               psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
+               psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
+               psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
+               psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
+               psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
+               psDevInfo->sDCJTable.pfnSetDCState = SetDCState;
+
+
+               if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (
+                       &psDevInfo->sDCJTable,
+                       &psDevInfo->uiDeviceID ) != PVRSRV_OK)
+               {
+                       return (MRST_ERROR_DEVICE_REGISTER_FAILED);
+               }
+
+               printk("Device ID: %d\n", (int)psDevInfo->uiDeviceID);
+
+#if 0
+#if defined (SYS_USING_INTERRUPTS)
+               if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterSystemISRHandler(MRSTLFBISRHandler,
+                                                                           psDevInfo,
+                                                                           0,
+                                                                           (IMG_UINT32)psDevInfo->uiDeviceID) != PVRSRV_OK)
+               {
+                       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX "ISR Installation failed\n"));
+                       return (MRST_ERROR_INIT_FAILURE);
+               }
+#endif
+
+               if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterPowerDevice((IMG_UINT32)psDevInfo->uiDeviceID,
+                                                                      MRSTLFBPrePowerState, MRSTLFBPostPowerState,
+                                                                      IMG_NULL, IMG_NULL,
+                                                                      psDevInfo,
+                                                                      PVRSRV_DEV_POWER_STATE_ON,
+                                                                      PVRSRV_DEV_POWER_STATE_ON) != PVRSRV_OK)
+               {
+                       return (MRST_ERROR_INIT_FAILURE);
+               }
+#endif
+
+#if defined (MRST_USING_INTERRUPTS)
+       
+       if(MRSTLFBInstallVSyncISR(psDevInfo,MRSTLFBVSyncISR) != MRST_OK)
+       {
+               DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX   "ISR Installation failed\n"));
+               return (MRST_ERROR_INIT_FAILURE);
+       }
+#endif
+
+       
+       pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
+       
+       
+       aui32SyncCountList[DC_FLIP_COMMAND][0] = 0; 
+       aui32SyncCountList[DC_FLIP_COMMAND][1] = 2; 
+       
+
+       if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList (psDevInfo->uiDeviceID,
+                                                               &pfnCmdProcList[0],
+                                                               aui32SyncCountList,
+                                                               MRSTLFB_COMMAND_COUNT) != PVRSRV_OK)
+         {
+           printk(KERN_WARNING DRIVER_PREFIX ": Can't register callback\n");
+           return (MRST_ERROR_CANT_REGISTER_CALLBACK);
+         }
+
+
+       }
+
+       
+       //psDrmPriv->psb_change_fb_handler = MRSTLFBHandleChangeFB;     
+
+       //psDrmPriv->psb_leave_vt_handler = DRMLFBLeaveVTHandler;
+       //psDrmPriv->psb_enter_vt_handler = DRMLFBEnterVTHandler;
+       
+       psDevInfo->ulRefCount++;
+
+       
+       return (MRST_OK);       
+}
+
+MRST_ERROR MRSTLFBDeinit(void)
+{
+       MRSTLFB_DEVINFO *psDevInfo, *psDevFirst;
+
+       psDevFirst = GetAnchorPtr();
+       psDevInfo = psDevFirst;
+
+
+       if (psDevInfo == NULL)
+       {
+               return (MRST_ERROR_GENERIC);
+       }
+
+
+       psDevInfo->ulRefCount--;
+
+       psDevInfo->psDrmDevice = NULL;
+       if (psDevInfo->ulRefCount == 0)
+       {
+
+               PVRSRV_DC_DISP2SRV_KMJTABLE     *psJTable = &psDevInfo->sPVRJTable;
+
+               if (psDevInfo->sPVRJTable.pfnPVRSRVRemoveCmdProcList (psDevInfo->uiDeviceID, MRSTLFB_COMMAND_COUNT) != PVRSRV_OK)
+               {
+                       return (MRST_ERROR_GENERIC);
+               }
+
+               if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterPowerDevice((IMG_UINT32)psDevInfo->uiDeviceID,
+                                                                      IMG_NULL, IMG_NULL,
+                                                                      IMG_NULL, IMG_NULL, IMG_NULL,
+                                                                      PVRSRV_DEV_POWER_STATE_ON,
+                                                                      PVRSRV_DEV_POWER_STATE_ON) != PVRSRV_OK)
+               {
+                       return (MRST_ERROR_GENERIC);
+               }
+
+#if 0 /* defined (SYS_USING_INTERRUPTS) */
+               if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterSystemISRHandler(IMG_NULL, IMG_NULL, 0,
+                                                                           (IMG_UINT32)psDevInfo->uiDeviceID) != PVRSRV_OK)
+               {
+                       return (MRST_ERROR_GENERIC);
+               }
+#endif
+
+#if defined (MRST_USING_INTERRUPTS)
+               
+               if(MRSTLFBUninstallVSyncISR(psDevInfo) != MRST_OK)
+               {
+                       return (MRST_ERROR_GENERIC);
+               }
+#endif
+
+               if (psJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->uiDeviceID) != PVRSRV_OK)
+               {
+                       return (MRST_ERROR_GENERIC);
+               }
+
+               DeInitDev(psDevInfo);
+
+
+               MRSTLFBFreeKernelMem(psDevInfo);
+       }
+
+
+       SetAnchorPtr(NULL);
+
+
+       return (MRST_OK);
+}
+
+MRST_ERROR MRSTLFBAllocBuffer(struct MRSTLFB_DEVINFO_TAG *psDevInfo, IMG_UINT32 ui32Size, MRSTLFB_BUFFER **ppBuffer)
+{
+       IMG_VOID *pvBuf;
+       IMG_UINT32 ulPagesNumber;
+       IMG_UINT32 ulCounter;
+       int i;
+
+       pvBuf = __vmalloc( ui32Size, GFP_KERNEL | __GFP_HIGHMEM, __pgprot((pgprot_val(PAGE_KERNEL ) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) );
+       if( pvBuf == NULL )
+       {
+               return MRST_ERROR_OUT_OF_MEMORY;
+       }
+
+       ulPagesNumber = (ui32Size + PAGE_SIZE -1) / PAGE_SIZE;
+
+       *ppBuffer = MRSTLFBAllocKernelMem( sizeof( MRSTLFB_BUFFER ) );
+       (*ppBuffer)->sCPUVAddr = pvBuf;
+       (*ppBuffer)->ui32BufferSize = ui32Size;
+       (*ppBuffer)->uSysAddr.psNonCont = MRSTLFBAllocKernelMem( sizeof( IMG_SYS_PHYADDR ) * ulPagesNumber);
+       (*ppBuffer)->bIsAllocated = MRST_TRUE;
+       (*ppBuffer)->bIsContiguous = MRST_FALSE;
+       (*ppBuffer)->ui32OwnerTaskID = task_tgid_nr(current);
+
+       i = 0;
+       for(ulCounter = 0; ulCounter < ui32Size; ulCounter += PAGE_SIZE)
+       {
+               (*ppBuffer)->uSysAddr.psNonCont[i++].uiAddr = vmalloc_to_pfn( pvBuf + ulCounter ) << PAGE_SHIFT;
+       }
+
+       psb_gtt_map_pvr_memory( psDevInfo->psDrmDevice,
+                                                       (unsigned int)*ppBuffer,
+                                                       (*ppBuffer)->ui32OwnerTaskID,
+                                                       (IMG_CPU_PHYADDR*) (*ppBuffer)->uSysAddr.psNonCont,
+                                                       ulPagesNumber,
+                                                       &(*ppBuffer)->sDevVAddr.uiAddr );
+
+       (*ppBuffer)->sDevVAddr.uiAddr <<= PAGE_SHIFT;
+
+       return MRST_OK;
+}
+
+MRST_ERROR MRSTLFBFreeBuffer(struct MRSTLFB_DEVINFO_TAG *psDevInfo, MRSTLFB_BUFFER **ppBuffer)
+{
+       if( !(*ppBuffer)->bIsAllocated )
+               return MRST_ERROR_INVALID_PARAMS;
+
+       psb_gtt_unmap_pvr_memory( psDevInfo->psDrmDevice,
+                                                         (unsigned int)*ppBuffer,
+                                                         (*ppBuffer)->ui32OwnerTaskID);
+
+       vfree( (*ppBuffer)->sCPUVAddr );
+
+       MRSTLFBFreeKernelMem( (*ppBuffer)->uSysAddr.psNonCont );
+
+       MRSTLFBFreeKernelMem( *ppBuffer);
+
+       *ppBuffer = NULL;
+
+       return MRST_OK;
+}
+
+#if 0
+/*
+ * save_display_registers
+ *
+ * Description: We are going to suspend so save current display
+ * register state.
+ */
+static void save_display_registers(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int i;
+
+       /* Display arbitration control + watermarks */
+       dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+       dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+       dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+       dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+       dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+       dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+       dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+       dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+       /* Pipe & plane A info */
+       dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
+       dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
+       dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
+       dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
+       dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
+       dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
+       dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
+       dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
+       dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
+       dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
+       dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
+       dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
+       dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
+       dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
+       dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
+       dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
+       dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
+       dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
+
+       /*save cursor regs*/
+       dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+       dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+       dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+       /*save palette (gamma) */
+       for (i = 0; i < 256; i++)
+               dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i<<2));
+
+       /*save performance state*/
+       dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
+
+       /* LVDS state */
+       dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
+       dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+       dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
+       dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
+       dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
+       dev_priv->saveLVDS = PSB_RVDC32(LVDS);
+       dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+       dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
+       dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
+       dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
+
+       /* HW overlay */
+       dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+       dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+       dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+       dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+       dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+       dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+       dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+       /* MIPI DSI */
+       dev_priv->saveMIPI = PSB_RVDC32(MIPI);
+       dev_priv->saveDEVICE_READY_REG = PSB_RVDC32(DEVICE_READY_REG);
+       dev_priv->saveINTR_EN_REG  = PSB_RVDC32(INTR_EN_REG);
+       dev_priv->saveDSI_FUNC_PRG_REG  = PSB_RVDC32(DSI_FUNC_PRG_REG);
+       dev_priv->saveHS_TX_TIMEOUT_REG = PSB_RVDC32(HS_TX_TIMEOUT_REG);
+       dev_priv->saveLP_RX_TIMEOUT_REG = PSB_RVDC32(LP_RX_TIMEOUT_REG);
+       dev_priv->saveTURN_AROUND_TIMEOUT_REG =
+                               PSB_RVDC32(TURN_AROUND_TIMEOUT_REG);
+       dev_priv->saveDEVICE_RESET_REG = PSB_RVDC32(DEVICE_RESET_REG);
+       dev_priv->saveDPI_RESOLUTION_REG =
+                               PSB_RVDC32(DPI_RESOLUTION_REG);
+       dev_priv->saveHORIZ_SYNC_PAD_COUNT_REG =
+                               PSB_RVDC32(HORIZ_SYNC_PAD_COUNT_REG);
+       dev_priv->saveHORIZ_BACK_PORCH_COUNT_REG =
+                               PSB_RVDC32(HORIZ_BACK_PORCH_COUNT_REG);
+       dev_priv->saveHORIZ_FRONT_PORCH_COUNT_REG =
+                               PSB_RVDC32(HORIZ_FRONT_PORCH_COUNT_REG);
+       dev_priv->saveHORIZ_ACTIVE_AREA_COUNT_REG =
+                               PSB_RVDC32(HORIZ_ACTIVE_AREA_COUNT_REG);
+       dev_priv->saveVERT_SYNC_PAD_COUNT_REG =
+                               PSB_RVDC32(VERT_SYNC_PAD_COUNT_REG);
+       dev_priv->saveVERT_BACK_PORCH_COUNT_REG =
+                               PSB_RVDC32(VERT_BACK_PORCH_COUNT_REG);
+       dev_priv->saveVERT_FRONT_PORCH_COUNT_REG =
+                               PSB_RVDC32(VERT_FRONT_PORCH_COUNT_REG);
+       dev_priv->saveHIGH_LOW_SWITCH_COUNT_REG =
+                               PSB_RVDC32(HIGH_LOW_SWITCH_COUNT_REG);
+       dev_priv->saveINIT_COUNT_REG = PSB_RVDC32(INIT_COUNT_REG);
+       dev_priv->saveMAX_RET_PAK_REG = PSB_RVDC32(MAX_RET_PAK_REG);
+       dev_priv->saveVIDEO_FMT_REG = PSB_RVDC32(VIDEO_FMT_REG);
+       dev_priv->saveEOT_DISABLE_REG = PSB_RVDC32(EOT_DISABLE_REG);
+       dev_priv->saveLP_BYTECLK_REG = PSB_RVDC32(LP_BYTECLK_REG);
+       dev_priv->saveHS_LS_DBI_ENABLE_REG =
+                               PSB_RVDC32(HS_LS_DBI_ENABLE_REG);
+       dev_priv->saveTXCLKESC_REG = PSB_RVDC32(TXCLKESC_REG);
+       dev_priv->saveDPHY_PARAM_REG  = PSB_RVDC32(DPHY_PARAM_REG);
+       dev_priv->saveMIPI_CONTROL_REG = PSB_RVDC32(MIPI_CONTROL_REG);
+
+       /* DPST registers */
+       dev_priv->saveHISTOGRAM_INT_CONTROL_REG = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+       dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+}
+
+
+/*
+ * restore_display_registers
+ *
+ * Description: We are going to resume so restore display register state.
+ */
+static void restore_display_registers(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       unsigned long i, pp_stat;
+
+       /* Display arbitration + watermarks */
+       PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+       PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+       PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+       PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+       PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+       PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+       PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+       PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+       /*make sure VGA plane is off. it initializes to on after reset!*/
+       PSB_WVDC32(0x80000000, VGACNTRL);
+
+       /* set the plls */
+       PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
+       PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
+       /* Actually enable it */
+       PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
+       DRM_UDELAY(150);
+
+       /* Restore mode */
+       PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
+       PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
+       PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
+       PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
+       PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
+       PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
+       PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
+       PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
+
+       /*restore performance mode*/
+       PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
+
+       /*enable the pipe*/
+       if (dev_priv->iLVDS_enable)
+               PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
+
+       /* set up MIPI */
+       PSB_WVDC32(dev_priv->saveINTR_EN_REG, INTR_EN_REG);
+       PSB_WVDC32(dev_priv->saveDSI_FUNC_PRG_REG, DSI_FUNC_PRG_REG);
+       PSB_WVDC32(dev_priv->saveHS_TX_TIMEOUT_REG, HS_TX_TIMEOUT_REG);
+       PSB_WVDC32(dev_priv->saveLP_RX_TIMEOUT_REG, LP_RX_TIMEOUT_REG);
+       PSB_WVDC32(dev_priv->saveTURN_AROUND_TIMEOUT_REG,
+                                       TURN_AROUND_TIMEOUT_REG);
+       PSB_WVDC32(dev_priv->saveDEVICE_RESET_REG, DEVICE_RESET_REG);
+       PSB_WVDC32(dev_priv->saveDPI_RESOLUTION_REG,
+                                       DPI_RESOLUTION_REG);
+       PSB_WVDC32(dev_priv->saveHORIZ_SYNC_PAD_COUNT_REG,
+                                       HORIZ_SYNC_PAD_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveHORIZ_BACK_PORCH_COUNT_REG,
+                                       HORIZ_BACK_PORCH_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveHORIZ_FRONT_PORCH_COUNT_REG,
+                                       HORIZ_FRONT_PORCH_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveHORIZ_ACTIVE_AREA_COUNT_REG,
+                                       HORIZ_ACTIVE_AREA_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveVERT_SYNC_PAD_COUNT_REG,
+                                       VERT_SYNC_PAD_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveVERT_BACK_PORCH_COUNT_REG,
+                                       VERT_BACK_PORCH_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveVERT_FRONT_PORCH_COUNT_REG,
+                                       VERT_FRONT_PORCH_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveHIGH_LOW_SWITCH_COUNT_REG,
+                                       HIGH_LOW_SWITCH_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveINIT_COUNT_REG, INIT_COUNT_REG);
+       PSB_WVDC32(dev_priv->saveMAX_RET_PAK_REG, MAX_RET_PAK_REG);
+       PSB_WVDC32(dev_priv->saveVIDEO_FMT_REG, VIDEO_FMT_REG);
+       PSB_WVDC32(dev_priv->saveEOT_DISABLE_REG, EOT_DISABLE_REG);
+       PSB_WVDC32(dev_priv->saveLP_BYTECLK_REG, LP_BYTECLK_REG);
+       PSB_WVDC32(dev_priv->saveHS_LS_DBI_ENABLE_REG,
+                                       HS_LS_DBI_ENABLE_REG);
+       PSB_WVDC32(dev_priv->saveTXCLKESC_REG, TXCLKESC_REG);
+       PSB_WVDC32(dev_priv->saveDPHY_PARAM_REG, DPHY_PARAM_REG);
+       PSB_WVDC32(dev_priv->saveMIPI_CONTROL_REG, MIPI_CONTROL_REG);
+
+       /*set up the plane*/
+       PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
+       PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
+       PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
+
+       /* Enable the plane */
+       PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
+       PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
+
+       /*Enable Cursor A*/
+       PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+       PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+       PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+       /* restore palette (gamma) */
+       /*DRM_UDELAY(50000); */
+       for (i = 0; i < 256; i++)
+               PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i<<2));
+
+       if (dev_priv->iLVDS_enable) {
+               PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
+               PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
+               PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+               PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+               PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
+               PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
+               PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
+               PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
+               PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
+               PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
+       } else { /* enable MIPI */
+               PSB_WVDC32(MIPI_PORT_EN | MIPI_BORDER_EN, MIPI); /*force on port*/
+               PSB_WVDC32(1, DEVICE_READY_REG);/* force on to re-program */
+               dev_priv->init_drvIC(dev);
+               PSB_WVDC32(dev_priv->saveMIPI, MIPI); /*port 61190h*/
+               PSB_WVDC32(dev_priv->saveDEVICE_READY_REG, DEVICE_READY_REG);
+               if (dev_priv->saveDEVICE_READY_REG)
+                       PSB_WVDC32(DPI_TURN_ON, DPI_CONTROL_REG);
+               PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
+               PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
+               PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
+       }
+
+       /*wait for cycle delay*/
+       do {
+               pp_stat = PSB_RVDC32(PP_STATUS);
+       } while (pp_stat & 0x08000000);
+
+       DRM_UDELAY(999);
+       /*wait for panel power up*/
+       do {
+               pp_stat = PSB_RVDC32(PP_STATUS);
+       } while (pp_stat & 0x10000000);
+
+       /* restore HW overlay */
+       PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+       PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+       /* DPST registers */
+       PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, HISTOGRAM_INT_CONTROL);
+       PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, HISTOGRAM_LOGIC_CONTROL);
+}
+
+
+PVRSRV_ERROR MRSTLFBPrePowerState(IMG_HANDLE            hDevHandle,
+                                 PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                 PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+       MRSTLFB_DEVINFO* psDevInfo = (MRSTLFB_DEVINFO *)hDevHandle;
+       struct drm_device* dev = psDevInfo->psDrmDevice;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int pp_stat;
+
+       if ((eNewPowerState == eCurrentPowerState) ||
+           (eNewPowerState == PVRSRV_DEV_POWER_STATE_ON))
+               return PVRSRV_OK;
+
+       if (!dev_priv->iLVDS_enable && dev_priv->dsi_prePowerState != NULL)
+               dev_priv->dsi_prePowerState(dev);
+
+       save_display_registers(dev);
+
+       if (dev_priv->iLVDS_enable) {
+               /*shutdown the panel*/
+               PSB_WVDC32(0, PP_CONTROL);
+
+               do {
+                       pp_stat = PSB_RVDC32(PP_STATUS);
+               } while (pp_stat & 0x80000000);
+
+               /*turn off the plane*/
+               PSB_WVDC32(0x58000000, DSPACNTR);
+               PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+               msleep(4);
+
+               /*turn off pipe*/
+               PSB_WVDC32(0x0, PIPEACONF);
+               msleep(8);
+
+               /*turn off PLLs*/
+               PSB_WVDC32(0, MRST_DPLL_A);
+       }
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR MRSTLFBPostPowerState(IMG_HANDLE            hDevHandle,
+                                  PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                  PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+       MRSTLFB_DEVINFO* psDevInfo = (MRSTLFB_DEVINFO *)hDevHandle;
+       struct drm_device* dev = psDevInfo->psDrmDevice;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_gtt *pg = dev_priv->pg;
+
+       if ((eNewPowerState == eCurrentPowerState) ||
+           (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+               return PVRSRV_OK;
+
+       PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+       pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+                             pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+       /* Don't reinitialize the GTT as it is unnecessary.  The gtt is
+        * stored in memory so it will automatically be restored.  All
+        * we need to do is restore the PGETBL_CTL which we already do
+        * above.
+        */
+       /*psb_gtt_init(dev_priv->pg, 1);*/
+
+       restore_display_registers(dev);
+
+       if (!dev_priv->iLVDS_enable && dev_priv->dsi_postPowerState != NULL)
+               dev_priv->dsi_postPowerState(dev);
+
+       return PVRSRV_OK;
+}
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb_linux.c b/drivers/staging/mrst/pvr/services4/3rdparty/linux_framebuffer_mrst/mrstlfb_linux.c
new file mode 100644 (file)
index 0000000..85b6799
--- /dev/null
@@ -0,0 +1,214 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+
+#include <drm/drmP.h>
+
+#include <asm/io.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "pvrmodule.h"
+#include "pvr_drm.h"
+#include "mrstlfb.h"
+#include "kerneldisplay.h"
+#include "psb_irq.h"
+
+#include "psb_drv.h"
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+
+#if !defined(SUPPORT_DRI_DRM)
+#error "SUPPORT_DRI_DRM must be set"
+#endif
+
+#define        MAKESTRING(x) # x
+
+#if !defined(DISPLAY_CONTROLLER)
+#define DISPLAY_CONTROLLER pvrlfb
+#endif
+
+//#define MAKENAME_HELPER(x, y) x ## y
+//#define      MAKENAME2(x, y) MAKENAME_HELPER(x, y)
+//#define      MAKENAME(x) MAKENAME2(DISPLAY_CONTROLLER, x)
+
+#define unref__ __attribute__ ((unused))
+
+void *MRSTLFBAllocKernelMem(unsigned long ulSize)
+{
+       return kmalloc(ulSize, GFP_KERNEL);
+}
+
+void MRSTLFBFreeKernelMem(void *pvMem)
+{
+       kfree(pvMem);
+}
+
+
+MRST_ERROR MRSTLFBGetLibFuncAddr (char *szFunctionName, PFN_DC_GET_PVRJTABLE *ppfnFuncTable)
+{
+       if(strcmp("PVRGetDisplayClassJTable", szFunctionName) != 0)
+       {
+               return (MRST_ERROR_INVALID_PARAMS);
+       }
+
+
+       *ppfnFuncTable = PVRGetDisplayClassJTable;
+
+       return (MRST_OK);
+}
+
+static void MRSTLFBVSyncWriteReg(MRSTLFB_DEVINFO *psDevInfo, unsigned long ulOffset, unsigned long ulValue)
+{
+
+       void *pvRegAddr = (void *)(psDevInfo->pvRegs + ulOffset);
+       mb();
+       iowrite32(ulValue, pvRegAddr);
+}
+
+unsigned long MRSTLFBVSyncReadReg(MRSTLFB_DEVINFO * psDevinfo, unsigned long ulOffset)
+{
+       mb();
+       return ioread32((char *)psDevinfo->pvRegs + ulOffset);
+}
+
+void MRSTLFBEnableVSyncInterrupt(MRSTLFB_DEVINFO * psDevinfo)
+{
+#if defined(MRST_USING_INTERRUPTS)
+    struct drm_psb_private *dev_priv =
+       (struct drm_psb_private *) psDevinfo->psDrmDevice->dev_private;
+    dev_priv->vblanksEnabledForFlips = true;
+    psb_enable_vblank(psDevinfo->psDrmDevice, 0);
+
+#endif
+}
+
+void MRSTLFBDisableVSyncInterrupt(MRSTLFB_DEVINFO * psDevinfo)
+{
+#if defined(MRST_USING_INTERRUPTS)
+    struct drm_device * dev = psDevinfo->psDrmDevice;
+    struct drm_psb_private *dev_priv =
+       (struct drm_psb_private *) psDevinfo->psDrmDevice->dev_private;
+    dev_priv->vblanksEnabledForFlips = false;
+    //Only turn off if DRM isn't currently using vblanks, otherwise, leave on.
+    if (!dev->vblank_enabled[0])
+    psb_disable_vblank(psDevinfo->psDrmDevice, 0);
+#endif
+}
+
+#if defined(MRST_USING_INTERRUPTS)
+MRST_ERROR MRSTLFBInstallVSyncISR(MRSTLFB_DEVINFO *psDevInfo, MRSTLFB_VSYNC_ISR_PFN pVsyncHandler)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) psDevInfo->psDrmDevice->dev_private;
+       dev_priv->psb_vsync_handler = pVsyncHandler;
+       return (MRST_OK);
+}
+
+
+MRST_ERROR MRSTLFBUninstallVSyncISR(MRSTLFB_DEVINFO    *psDevInfo)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) psDevInfo->psDrmDevice->dev_private;
+       dev_priv->psb_vsync_handler = NULL;
+       return (MRST_OK);
+}
+#endif 
+
+
+void MRSTLFBFlipToSurface(MRSTLFB_DEVINFO *psDevInfo,  unsigned long uiAddr)
+{
+       int dspbase = (psDevInfo->ui32MainPipe == 0 ? DSPABASE : DSPBBASE);
+       int dspsurf = (psDevInfo->ui32MainPipe == 0 ? DSPASURF : DSPBSURF);
+       int panel_type;
+
+       panel_type = is_panel_vid_or_cmd(psDevInfo->psDrmDevice);
+
+       if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+       {
+               dspsurf = DSPASURF;
+               MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr);
+#if defined(CONFIG_MDFD_DUAL_MIPI)
+               dspsurf = DSPCSURF;
+               MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr);
+#endif
+
+               if (panel_type == MDFLD_DSI_ENCODER_DBI) {
+#if defined(CONFIG_MDFLD_DSI_DPU)
+                       mdfld_dbi_dpu_report_fullscreen_damage(psDevInfo->psDrmDevice);
+#elif defined(CONFIG_MDFLD_DSI_DSR)
+                       /*if in DSR mode, exit it!*/
+                       mdfld_dsi_dbi_exit_dsr (psDevInfo->psDrmDevice, MDFLD_DSR_2D_3D);
+#endif
+               }
+
+               dspsurf = DSPBSURF;
+               MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr);
+               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+       }
+}
+
+
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device unref__ *dev)
+{
+       if(MRSTLFBInit(dev) != MRST_OK)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX ": MRSTLFB_Init: MRSTLFBInit failed\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device unref__ *dev)
+{    
+       if(MRSTLFBDeinit() != MRST_OK)
+       {
+               printk(KERN_WARNING DRIVER_PREFIX "%s: can't deinit device\n", __FUNCTION__);
+       }
+}
+
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Suspend)(struct drm_device unref__ *dev)
+{
+       MRSTLFBSuspend();
+
+       return 0;
+}
+
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Resume)(struct drm_device unref__ *dev)
+{
+       MRSTLFBResume();
+
+       return 0;
+}
diff --git a/drivers/staging/mrst/pvr/services4/include/env/linux-intel/pvr_drm_shared.h b/drivers/staging/mrst/pvr/services4/include/env/linux-intel/pvr_drm_shared.h
new file mode 100644 (file)
index 0000000..573d9b9
--- /dev/null
@@ -0,0 +1,54 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_SHARED_H__)
+#define __PVR_DRM_SHARED_H__
+
+#if defined(SUPPORT_DRI_DRM)
+
+#define PVR_DRM_SRVKM_CMD      0x12
+#define        PVR_DRM_DISP_CMD        0x13
+#define        PVR_DRM_BC_CMD          0x14
+#define PVR_DRM_IS_MASTER_CMD  0x15
+#define PVR_DRM_UNPRIV_CMD     0x16
+#define PVR_DRM_DBGDRV_CMD     0x1E
+
+#define        PVR_DRM_UNPRIV_INIT_SUCCESFUL   0
+#define        PVR_DRM_UNPRIV_BUSID_TYPE       1
+#define        PVR_DRM_UNPRIV_BUSID_FIELD      2
+
+#define        PVR_DRM_BUS_TYPE_PCI            0
+
+#define        PVR_DRM_PCI_DOMAIN              0
+#define        PVR_DRM_PCI_BUS                 1
+#define        PVR_DRM_PCI_DEV                 2
+#define        PVR_DRM_PCI_FUNC                3
+
+#endif
+
+#endif
+
+
diff --git a/drivers/staging/mrst/pvr/services4/include/env/linux/pvr_drm_shared.h b/drivers/staging/mrst/pvr/services4/include/env/linux/pvr_drm_shared.h
new file mode 100644 (file)
index 0000000..573d9b9
--- /dev/null
@@ -0,0 +1,54 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_SHARED_H__)
+#define __PVR_DRM_SHARED_H__
+
+#if defined(SUPPORT_DRI_DRM)
+
+#define PVR_DRM_SRVKM_CMD      0x12
+#define        PVR_DRM_DISP_CMD        0x13
+#define        PVR_DRM_BC_CMD          0x14
+#define PVR_DRM_IS_MASTER_CMD  0x15
+#define PVR_DRM_UNPRIV_CMD     0x16
+#define PVR_DRM_DBGDRV_CMD     0x1E
+
+#define        PVR_DRM_UNPRIV_INIT_SUCCESFUL   0
+#define        PVR_DRM_UNPRIV_BUSID_TYPE       1
+#define        PVR_DRM_UNPRIV_BUSID_FIELD      2
+
+#define        PVR_DRM_BUS_TYPE_PCI            0
+
+#define        PVR_DRM_PCI_DOMAIN              0
+#define        PVR_DRM_PCI_BUS                 1
+#define        PVR_DRM_PCI_DEV                 2
+#define        PVR_DRM_PCI_FUNC                3
+
+#endif
+
+#endif
+
+
diff --git a/drivers/staging/mrst/pvr/services4/include/kernelbuffer.h b/drivers/staging/mrst/pvr/services4/include/kernelbuffer.h
new file mode 100644 (file)
index 0000000..5243aaf
--- /dev/null
@@ -0,0 +1,72 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined (__KERNELBUFFER_H__)
+#define __KERNELBUFFER_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef PVRSRV_ERROR (*PFN_OPEN_BC_DEVICE)(IMG_UINT32, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_BC_DEVICE)(IMG_UINT32, IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_GET_BC_INFO)(IMG_HANDLE, BUFFER_INFO*);
+typedef PVRSRV_ERROR (*PFN_GET_BC_BUFFER)(IMG_HANDLE, IMG_UINT32, PVRSRV_SYNC_DATA*, IMG_HANDLE*);
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG
+{
+       IMG_UINT32                                                      ui32TableSize;
+       PFN_OPEN_BC_DEVICE                                      pfnOpenBCDevice;
+       PFN_CLOSE_BC_DEVICE                                     pfnCloseBCDevice;
+       PFN_GET_BC_INFO                                         pfnGetBCInfo;
+       PFN_GET_BC_BUFFER                                       pfnGetBCBuffer;
+       PFN_GET_BUFFER_ADDR                                     pfnGetBufferAddr;
+
+} PVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+
+typedef PVRSRV_ERROR (*PFN_BC_REGISTER_BUFFER_DEV)(PVRSRV_BC_SRV2BUFFER_KMJTABLE*, IMG_UINT32*);
+typedef IMG_VOID (*PFN_BC_SCHEDULE_DEVICES)(IMG_VOID);
+typedef PVRSRV_ERROR (*PFN_BC_REMOVE_BUFFER_DEV)(IMG_UINT32);  
+
+typedef struct PVRSRV_BC_BUFFER2SRV_KMJTABLE_TAG
+{
+       IMG_UINT32                                                      ui32TableSize;
+       PFN_BC_REGISTER_BUFFER_DEV                      pfnPVRSRVRegisterBCDevice;
+       PFN_BC_SCHEDULE_DEVICES                         pfnPVRSRVScheduleDevices;
+       PFN_BC_REMOVE_BUFFER_DEV                        pfnPVRSRVRemoveBCDevice;
+
+} PVRSRV_BC_BUFFER2SRV_KMJTABLE, *PPVRSRV_BC_BUFFER2SRV_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_BC_GET_PVRJTABLE) (PPVRSRV_BC_BUFFER2SRV_KMJTABLE); 
+
+IMG_IMPORT IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/include/kerneldisplay.h b/drivers/staging/mrst/pvr/services4/include/kerneldisplay.h
new file mode 100644 (file)
index 0000000..b5c1c7a
--- /dev/null
@@ -0,0 +1,165 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined (__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef PVRSRV_ERROR (*PFN_OPEN_DC_DEVICE)(IMG_UINT32, IMG_HANDLE*, PVRSRV_SYNC_DATA*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_DC_DEVICE)(IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_FORMATS)(IMG_HANDLE, IMG_UINT32*, DISPLAY_FORMAT*);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_DIMS)(IMG_HANDLE,
+                                                                                DISPLAY_FORMAT*,
+                                                                                IMG_UINT32*,
+                                                                                DISPLAY_DIMS*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_SYSTEMBUFFER)(IMG_HANDLE, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_INFO)(IMG_HANDLE, DISPLAY_INFO*);
+typedef PVRSRV_ERROR (*PFN_CREATE_DC_SWAPCHAIN)(IMG_HANDLE,
+                                                                                               IMG_UINT32, 
+                                                                                               DISPLAY_SURF_ATTRIBUTES*, 
+                                                                                               DISPLAY_SURF_ATTRIBUTES*,
+                                                                                               IMG_UINT32, 
+                                                                                               PVRSRV_SYNC_DATA**,
+                                                                                               IMG_UINT32,
+                                                                                               IMG_HANDLE*, 
+                                                                                               IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DESTROY_DC_SWAPCHAIN)(IMG_HANDLE, 
+                                                                                                IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_GET_DC_BUFFERS)(IMG_HANDLE,
+                                                                                  IMG_HANDLE,
+                                                                                  IMG_UINT32*,
+                                                                                  IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_BUFFER)(IMG_HANDLE,
+                                                                                         IMG_HANDLE,
+                                                                                         IMG_UINT32,
+                                                                                         IMG_HANDLE,
+                                                                                         IMG_UINT32,
+                                                                                         IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_SYSTEM)(IMG_HANDLE, IMG_HANDLE);
+typedef IMG_VOID (*PFN_QUERY_SWAP_COMMAND_ID)(IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_UINT16*, IMG_BOOL*);
+typedef IMG_VOID (*PFN_SET_DC_STATE)(IMG_HANDLE, IMG_UINT32);
+
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG
+{
+       IMG_UINT32                                              ui32TableSize;
+       PFN_OPEN_DC_DEVICE                              pfnOpenDCDevice;
+       PFN_CLOSE_DC_DEVICE                             pfnCloseDCDevice;
+       PFN_ENUM_DC_FORMATS                             pfnEnumDCFormats;
+       PFN_ENUM_DC_DIMS                                pfnEnumDCDims;
+       PFN_GET_DC_SYSTEMBUFFER                 pfnGetDCSystemBuffer;
+       PFN_GET_DC_INFO                                 pfnGetDCInfo;
+       PFN_GET_BUFFER_ADDR                             pfnGetBufferAddr;
+       PFN_CREATE_DC_SWAPCHAIN                 pfnCreateDCSwapChain;
+       PFN_DESTROY_DC_SWAPCHAIN                pfnDestroyDCSwapChain;
+       PFN_SET_DC_DSTRECT                              pfnSetDCDstRect;
+       PFN_SET_DC_SRCRECT                              pfnSetDCSrcRect;
+       PFN_SET_DC_DSTCK                                pfnSetDCDstColourKey;
+       PFN_SET_DC_SRCCK                                pfnSetDCSrcColourKey;
+       PFN_GET_DC_BUFFERS                              pfnGetDCBuffers;
+       PFN_SWAP_TO_DC_BUFFER                   pfnSwapToDCBuffer;
+       PFN_SWAP_TO_DC_SYSTEM                   pfnSwapToDCSystem;
+       PFN_SET_DC_STATE                                pfnSetDCState;
+       PFN_QUERY_SWAP_COMMAND_ID               pfnQuerySwapCommandID;
+
+} PVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_ISR_HANDLER)(IMG_VOID*);
+
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_DISPLAY_DEV)(PVRSRV_DC_SRV2DISP_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_DISPLAY_DEV)(IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_OEM_FUNCTION)(IMG_UINT32, IMG_VOID*, IMG_UINT32, IMG_VOID*, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_COMMANDPROCLIST)(IMG_UINT32, PPFN_CMD_PROC,IMG_UINT32[][2], IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_COMMANDPROCLIST)(IMG_UINT32, IMG_UINT32);
+typedef IMG_VOID (*PFN_DC_CMD_COMPLETE)(IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_SYS_ISR)(PFN_ISR_HANDLER, IMG_VOID*, IMG_UINT32, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_POWER)(IMG_UINT32, PFN_PRE_POWER, PFN_POST_POWER,
+                                                                                         PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE,
+                                                                                         IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE);
+
+typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG
+{
+       IMG_UINT32                                              ui32TableSize;
+       PFN_DC_REGISTER_DISPLAY_DEV             pfnPVRSRVRegisterDCDevice;
+       PFN_DC_REMOVE_DISPLAY_DEV               pfnPVRSRVRemoveDCDevice;
+       PFN_DC_OEM_FUNCTION                             pfnPVRSRVOEMFunction;
+       PFN_DC_REGISTER_COMMANDPROCLIST pfnPVRSRVRegisterCmdProcList;
+       PFN_DC_REMOVE_COMMANDPROCLIST   pfnPVRSRVRemoveCmdProcList;
+       PFN_DC_CMD_COMPLETE                             pfnPVRSRVCmdComplete;
+       PFN_DC_REGISTER_SYS_ISR                 pfnPVRSRVRegisterSystemISRHandler;
+       PFN_DC_REGISTER_POWER                   pfnPVRSRVRegisterPowerDevice;
+       PFN_DC_CMD_COMPLETE                             pfnPVRSRVFreeCmdCompletePacket;
+} PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND_TAG
+{
+       
+       IMG_HANDLE hExtDevice;
+
+       
+       IMG_HANDLE hExtSwapChain;
+
+       
+       IMG_HANDLE hExtBuffer;
+
+       
+       IMG_HANDLE hPrivateTag;
+
+       
+       IMG_UINT32 ui32ClipRectCount;
+
+       
+       IMG_RECT *psClipRect;
+
+       
+       IMG_UINT32      ui32SwapInterval;
+
+} DISPLAYCLASS_FLIP_COMMAND;
+
+#define DC_FLIP_COMMAND                0
+
+#define DC_STATE_NO_FLUSH_COMMANDS             0
+#define DC_STATE_FLUSH_COMMANDS                        1
+
+
+typedef IMG_BOOL (*PFN_DC_GET_PVRJTABLE)(PPVRSRV_DC_DISP2SRV_KMJTABLE);
+
+IMG_IMPORT IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/include/pdump.h b/drivers/staging/mrst/pvr/services4/include/pdump.h
new file mode 100644 (file)
index 0000000..78d9073
--- /dev/null
@@ -0,0 +1,37 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _SERVICES_PDUMP_H_
+#define _SERVICES_PDUMP_H_
+
+#define PDUMP_FLAGS_NEVER                      0x08000000U
+#define PDUMP_FLAGS_LASTFRAME          0x10000000U
+#define PDUMP_FLAGS_RESETLFBUFFER      0x20000000U
+#define PDUMP_FLAGS_CONTINUOUS         0x40000000U
+#define PDUMP_FLAGS_PERSISTENT         0x80000000U
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/include/pvr_bridge.h b/drivers/staging/mrst/pvr/services4/include/pvr_bridge.h
new file mode 100644 (file)
index 0000000..10871b4
--- /dev/null
@@ -0,0 +1,1471 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_H__
+#define __PVR_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesint.h"
+
+#ifdef __linux__
+
+               #include <linux/ioctl.h>
+    
+    #define PVRSRV_IOC_GID      'g'
+    #define PVRSRV_IO(INDEX)    _IO(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+    #define PVRSRV_IOW(INDEX)   _IOW(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+    #define PVRSRV_IOR(INDEX)   _IOR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+    #define PVRSRV_IOWR(INDEX)  _IOWR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+
+#else 
+
+                       #error Unknown platform: Cannot define ioctls
+
+       #define PVRSRV_IO(INDEX)    (PVRSRV_IOC_GID + (INDEX))
+       #define PVRSRV_IOW(INDEX)   (PVRSRV_IOC_GID + (INDEX))
+       #define PVRSRV_IOR(INDEX)   (PVRSRV_IOC_GID + (INDEX))
+       #define PVRSRV_IOWR(INDEX)  (PVRSRV_IOC_GID + (INDEX))
+
+       #define PVRSRV_BRIDGE_BASE                  PVRSRV_IOC_GID
+#endif 
+
+
+#define PVRSRV_BRIDGE_CORE_CMD_FIRST                   0UL
+#define PVRSRV_BRIDGE_ENUM_DEVICES                             PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0)     
+#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO               PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1)     
+#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO               PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2)     
+#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT             PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3)     
+#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT            PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4)     
+#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO              PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5)     
+#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM                  PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6)     
+#define PVRSRV_BRIDGE_FREE_DEVICEMEM                   PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7)     
+#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM                        PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8)     
+#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE              PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9)     
+#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE             PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10)    
+#define        PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA           PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11)   
+#define PVRSRV_BRIDGE_CONNECT_SERVICES                 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12)    
+#define PVRSRV_BRIDGE_DISCONNECT_SERVICES              PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13)    
+#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM                  PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14)    
+#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO                        PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15)    
+#define PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM              PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_FREE_DEV_VIRTMEM                 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_MAP_EXT_MEMORY                   PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_UNMAP_EXT_MEMORY                 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY                   PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_UNMAP_DEV_MEMORY                 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY   PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+22)
+#define PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+23)
+#define PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER             PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+24)
+#define PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM                 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
+#define PVRSRV_BRIDGE_RELEASE_MMAP_DATA                        PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+#define PVRSRV_BRIDGE_CORE_CMD_LAST                            (PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+
+#define PVRSRV_BRIDGE_SIM_CMD_FIRST                            (PVRSRV_BRIDGE_CORE_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT             PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0)      
+#define PVRSRV_BRIDGE_REGISTER_SIM_PROCESS             PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+1)      
+#define PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS   PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)      
+#define PVRSRV_BRIDGE_SIM_CMD_LAST                             (PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_MAPPING_CMD_FIRST                        (PVRSRV_BRIDGE_SIM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE               PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+0)  
+#define PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE             PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+1)  
+#define PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP            PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)  
+#define PVRSRV_BRIDGE_MAPPING_CMD_LAST                 (PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_STATS_CMD_FIRST                  (PVRSRV_BRIDGE_MAPPING_CMD_LAST+1)
+#define        PVRSRV_BRIDGE_GET_FB_STATS                              PVRSRV_IOWR(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)    
+#define PVRSRV_BRIDGE_STATS_CMD_LAST                   (PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_MISC_CMD_FIRST                   (PVRSRV_BRIDGE_STATS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_MISC_INFO                            PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+0)     
+#define PVRSRV_BRIDGE_RELEASE_MISC_INFO                        PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)     
+#define PVRSRV_BRIDGE_MISC_CMD_LAST                            (PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST                        (PVRSRV_BRIDGE_MISC_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES              PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+0)  
+#define PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES            PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)  
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST                 (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#else
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST                 PVRSRV_BRIDGE_MISC_CMD_LAST
+#endif
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST                  (PVRSRV_BRIDGE_OVERLAY_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PDUMP_INIT                       PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)    
+#define PVRSRV_BRIDGE_PDUMP_MEMPOL                     PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)    
+#define PVRSRV_BRIDGE_PDUMP_DUMPMEM                    PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)    
+#define PVRSRV_BRIDGE_PDUMP_REG                                PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)    
+#define PVRSRV_BRIDGE_PDUMP_REGPOL                     PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)    
+#define PVRSRV_BRIDGE_PDUMP_COMMENT                    PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)    
+#define PVRSRV_BRIDGE_PDUMP_SETFRAME                   PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)    
+#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING                        PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)    
+#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP                 PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8)    
+#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG                        PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9)    
+#define PVRSRV_BRIDGE_PDUMP_SYNCPOL                    PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10)   
+#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC                   PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11)   
+#define PVRSRV_BRIDGE_PDUMP_MEMPAGES                   PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12)   
+#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO                 PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13)   
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR             PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)   
+#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ       PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_PDUMP_STARTINITPHASE                     PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_PDUMP_STOPINITPHASE                      PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST                   (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#else
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST                   PVRSRV_BRIDGE_OVERLAY_CMD_LAST
+#endif
+
+#define PVRSRV_BRIDGE_OEM_CMD_FIRST                            (PVRSRV_BRIDGE_PDUMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_OEMJTABLE                            PVRSRV_IOWR(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)      
+#define PVRSRV_BRIDGE_OEM_CMD_LAST                             (PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST               (PVRSRV_BRIDGE_OEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ENUM_CLASS                               PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_LAST                        (PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST              (PVRSRV_BRIDGE_DEVCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE            PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE   PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS   PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS              PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER  PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_INFO               PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN               PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN              PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT            PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT            PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY               PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY               PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS            PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_FRONT_BUFFER               PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_LAST               (PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST               (PVRSRV_BRIDGE_DISPCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE  PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO             PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER   PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_LAST                        (PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_WRAP_CMD_FIRST                   (PVRSRV_BRIDGE_BUFCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_WRAP_EXT_MEMORY                  PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY                        PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_WRAP_CMD_LAST                            (PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST              (PVRSRV_BRIDGE_WRAP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM             PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM              PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MAP_MEMINFO_MEM                  PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_UNMAP_MEMINFO_MEM                        PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST               (PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST  (PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR        PVRSRV_IOWR(PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST   (PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_INITSRV_CMD_FIRST                        (PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INITSRV_CONNECT                  PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_INITSRV_DISCONNECT               PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_INITSRV_CMD_LAST                 (PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST   (PVRSRV_BRIDGE_INITSRV_CMD_LAST+1)      
+#define PVRSRV_BRIDGE_EVENT_OBJECT_WAIT                        PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_OPEN                        PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE               PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST            (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST               (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST+1)
+#define PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ        PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS  PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ        PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA  PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_ALLOC_SYNC_INFO           PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_FREE_SYNC_INFO            PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST                        (PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+7)
+       
+#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD              (PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST+1)
+
+
+#define PVRSRV_KERNEL_MODE_CLIENT                              1
+
+typedef struct PVRSRV_BRIDGE_RETURN_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_VOID *pvData;
+
+}PVRSRV_BRIDGE_RETURN;
+
+
+typedef struct PVRSRV_BRIDGE_PACKAGE_TAG
+{
+       IMG_UINT32                              ui32BridgeID;                   
+       IMG_UINT32                              ui32Size;                               
+       IMG_VOID                                *pvParamIn;                              
+       IMG_UINT32                              ui32InBufferSize;               
+       IMG_VOID                                *pvParamOut;                    
+       IMG_UINT32                              ui32OutBufferSize;              
+
+       IMG_HANDLE                              hKernelServices;                
+}PVRSRV_BRIDGE_PACKAGE;
+
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_CONNECT_SERVICES_TAG
+{
+       IMG_UINT32              ui32BridgeFlags;
+       IMG_UINT32              ui32Flags;
+} PVRSRV_BRIDGE_IN_CONNECT_SERVICES;
+
+typedef struct PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_UINT32                      uiDevIndex;
+       PVRSRV_DEVICE_TYPE      eDeviceType;
+
+} PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUMCLASS_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       PVRSRV_DEVICE_CLASS sDeviceClass;
+} PVRSRV_BRIDGE_IN_ENUMCLASS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+} PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+
+} PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       PVRSRV_DEVICE_CLASS DeviceClass;
+       IMG_VOID*                       pvDevInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_HANDLE                      hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+
+}PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_HANDLE                      hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_HANDLE                      hDevMemHeap;
+       IMG_UINT32                      ui32Attribs;
+       IMG_SIZE_T                      ui32Size;
+       IMG_SIZE_T                      ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM;
+
+typedef struct PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+
+}PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       IMG_PVOID                                pvLinAddr;
+       IMG_HANDLE                               hMappingInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER;
+
+typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+
+}PVRSRV_BRIDGE_IN_FREEDEVICEMEM;
+
+typedef struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+
+}PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM;
+
+typedef struct PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_UINT32                      ui32Flags;
+
+} PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM;
+
+typedef struct PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_SIZE_T                      ui32QueueSize;
+
+}PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       PVRSRV_QUEUE_INFO       *psQueueInfo;
+
+}PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hMHandle;        
+} PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hMHandle;        
+} PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevMemHeap;
+       IMG_DEV_VIRTADDR        *psDevVAddr;
+       IMG_SIZE_T                      ui32Size;
+       IMG_SIZE_T                      ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES_TAG
+{
+       PVRSRV_ERROR                    eError;
+       IMG_HANDLE              hKernelServices;
+}PVRSRV_BRIDGE_OUT_CONNECT_SERVICES;
+
+typedef struct PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM_TAG
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hKernelMemInfo;
+       IMG_HANDLE                              hDstDevMemHeap;
+
+}PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY_TAG
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_KERNEL_MEM_INFO  *psDstKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  sDstClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sDstClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY_TAG
+{
+       IMG_UINT32                                      ui32BridgeFlags; 
+       PVRSRV_KERNEL_MEM_INFO          *psKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO          sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO         sClientSyncInfo;        
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       IMG_SYS_PHYADDR                 *psSysPAddr;
+       IMG_UINT32                              ui32Flags;
+
+}PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY_TAG
+{
+       IMG_UINT32                                      ui32BridgeFlags; 
+       PVRSRV_CLIENT_MEM_INFO          sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO         sClientSyncInfo;
+       IMG_UINT32                                      ui32Flags;
+
+}PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY;
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY_TAG
+{
+       IMG_UINT32                                      ui32BridgeFlags; 
+       IMG_HANDLE              hDeviceClassBuffer;
+       IMG_HANDLE              hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY_TAG
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       IMG_HANDLE                              hMappingInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPOL_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       IMG_UINT32 ui32Offset;
+       IMG_UINT32 ui32Value;
+       IMG_UINT32 ui32Mask;
+       PDUMP_POLL_OPERATOR             eOperator;
+       IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPOL;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+       IMG_BOOL bIsRead;
+       IMG_UINT32 ui32Value;
+       IMG_UINT32 ui32Mask;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_PVOID pvLinAddr;
+       IMG_PVOID pvAltLinAddr;
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       IMG_UINT32 ui32Offset;
+       IMG_UINT32 ui32Bytes;
+       IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_PVOID pvAltLinAddr;
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+       IMG_UINT32 ui32Offset;
+       IMG_UINT32 ui32Bytes;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPREG_TAG
+{
+       IMG_UINT32              ui32BridgeFlags; 
+       IMG_HANDLE              hDevCookie;
+       PVRSRV_HWREG    sHWReg;
+       IMG_UINT32              ui32Flags;
+       IMG_CHAR                szRegRegion[32];
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPREG;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       PVRSRV_HWREG sHWReg;
+       IMG_UINT32 ui32Mask;
+       IMG_UINT32 ui32Flags;
+       IMG_CHAR                szRegRegion[32];
+}PVRSRV_BRIDGE_IN_PDUMP_REGPOL;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       PVRSRV_HWREG sHWReg;
+       IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hKernelMemInfo;
+       IMG_DEV_PHYADDR         *pPages;
+       IMG_UINT32                      ui32NumPages;
+       IMG_DEV_VIRTADDR        sDevAddr;
+       IMG_UINT32                      ui32Start;
+       IMG_UINT32                      ui32Length;
+       IMG_BOOL                        bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_COMMENT_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_CHAR szComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+       IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_COMMENT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SETFRAME_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_UINT32 ui32Frame;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SETFRAME;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BITMAP_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+       IMG_UINT32 ui32FileOffset;
+       IMG_UINT32 ui32Width;
+       IMG_UINT32 ui32Height;
+       IMG_UINT32 ui32StrideInBytes;
+       IMG_DEV_VIRTADDR sDevBaseAddr;
+       IMG_HANDLE hDevMemContext;
+       IMG_UINT32 ui32Size;
+       PDUMP_PIXEL_FORMAT ePixelFormat;
+       PDUMP_MEM_FORMAT eMemFormat;
+       IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_BITMAP;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_READREG_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+       IMG_UINT32 ui32FileOffset;
+       IMG_UINT32 ui32Address;
+       IMG_UINT32 ui32Size;
+       IMG_UINT32 ui32Flags;
+       IMG_CHAR szRegRegion[32];
+
+}PVRSRV_BRIDGE_IN_PDUMP_READREG;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_CHAR szString[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+       IMG_BOOL bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hKernelMemInfo;
+       IMG_UINT32 ui32Offset;
+       IMG_DEV_PHYADDR sPDDevPAddr;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_PDUM_IN_CYCLE_COUNT_REG_READ_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_UINT32 ui32RegOffset;
+       IMG_BOOL bLastFrame;
+}PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ;
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMDEVICE_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32NumDevices;
+       PVRSRV_DEVICE_IDENTIFIER asDeviceIdentifier[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMDEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO_TAG
+{
+
+       PVRSRV_ERROR            eError;
+       IMG_HANDLE                      hDevCookie;
+
+} PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMCLASS_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32NumDevices;
+       IMG_UINT32 ui32DevID[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMCLASS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE_TAG
+{
+       IMG_UINT32              ui32BridgeFlags; 
+       IMG_UINT32              ui32DeviceID;
+       IMG_HANDLE              hDevCookie;
+       
+}PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE;
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE_TAG
+{
+       PVRSRV_ERROR    eError;
+       IMG_HANDLE              hDeviceKM;
+
+}PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE              hDevCookie;
+       IMG_HANDLE                              hDevMemContext;
+       IMG_VOID                                *pvLinAddr;
+       IMG_SIZE_T              ui32ByteSize;
+       IMG_SIZE_T              ui32PageOffset;
+       IMG_BOOL                bPhysContig;
+       IMG_UINT32                              ui32NumPageTableEntries;
+       IMG_SYS_PHYADDR         *psSysPAddr;
+       IMG_UINT32                              ui32Flags;
+
+}PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY;
+
+typedef struct PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY_TAG
+{
+       PVRSRV_ERROR    eError;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY;
+
+typedef struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY;
+
+
+#define PVRSRV_MAX_DC_DISPLAY_FORMATS                  10
+#define PVRSRV_MAX_DC_DISPLAY_DIMENSIONS               10
+#define PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS                        4
+#define PVRSRV_MAX_DC_CLIP_RECTS                               32
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS_TAG
+{
+       PVRSRV_ERROR    eError;
+       IMG_UINT32              ui32Count;
+       DISPLAY_FORMAT  asFormat[PVRSRV_MAX_DC_DISPLAY_FORMATS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS_TAG
+{
+       IMG_UINT32              ui32BridgeFlags; 
+       IMG_HANDLE              hDeviceKM;
+       DISPLAY_FORMAT  sFormat;
+
+}PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS_TAG
+{
+       PVRSRV_ERROR    eError;
+       IMG_UINT32              ui32Count;
+       DISPLAY_DIMS    asDim[PVRSRV_MAX_DC_DISPLAY_DIMENSIONS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO_TAG
+{
+       PVRSRV_ERROR    eError;
+       DISPLAY_INFO    sDisplayInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER_TAG
+{
+       PVRSRV_ERROR    eError;
+       IMG_HANDLE              hBuffer;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDeviceKM;
+       IMG_UINT32                              ui32Flags;
+       DISPLAY_SURF_ATTRIBUTES sDstSurfAttrib;
+       DISPLAY_SURF_ATTRIBUTES sSrcSurfAttrib;
+       IMG_UINT32                              ui32BufferCount;
+       IMG_UINT32                              ui32OEMFlags;
+       IMG_UINT32                              ui32SwapChainID;
+
+} PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_HANDLE                      hSwapChain;
+       IMG_UINT32                      ui32SwapChainID;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+       IMG_HANDLE                      hSwapChain;
+
+} PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+       IMG_HANDLE                      hSwapChain;
+       IMG_RECT                        sRect;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+       IMG_HANDLE                      hSwapChain;
+       IMG_UINT32                      ui32CKColour;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+       IMG_HANDLE                      hSwapChain;
+
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_UINT32                      ui32BufferCount;
+       IMG_HANDLE                      ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+
+} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+       IMG_HANDLE                      hBuffer;
+       IMG_UINT32                      ui32SwapInterval;
+       IMG_HANDLE                      hPrivateTag;
+       IMG_UINT32                      ui32ClipRectCount;
+       IMG_RECT                        sClipRect[PVRSRV_MAX_DC_CLIP_RECTS];
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+       IMG_HANDLE                      hSwapChain;
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_FRONT_BUFFER_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags;
+       IMG_HANDLE                      hDeviceKM;
+
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_FRONT_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_FRONT_BUFFER_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_UINT32                      ui32BufferIndex;
+       IMG_UINT32          ui32FlipChainID;
+
+} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_FRONT_BUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_UINT32                      ui32DeviceID;
+       IMG_HANDLE                      hDevCookie;
+       
+} PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_HANDLE                      hDeviceKM;
+
+} PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO_TAG
+{
+       PVRSRV_ERROR            eError;
+       BUFFER_INFO                     sBufferInfo;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDeviceKM;
+       IMG_UINT32                      ui32BufferIndex;
+
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_HANDLE                      hBuffer;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_UINT32                      ui32ClientHeapCount;
+       PVRSRV_HEAP_INFO        sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_HANDLE                      hDevMemContext;
+       IMG_UINT32                      ui32ClientHeapCount;
+       PVRSRV_HEAP_INFO        sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_HANDLE                      hDevMemHeap;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM_TAG
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+} PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM_TAG
+{
+       PVRSRV_ERROR                    eError;
+       IMG_HANDLE                              hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+       IMG_UINT64                              ui64Stamp;
+#endif
+
+} PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER_TAG
+{
+       PVRSRV_ERROR                    eError;
+       IMG_PVOID                               pvLinAddr;
+       IMG_HANDLE                              hMappingInfo;
+
+}PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_SIZE_T ui32Total;
+       IMG_SIZE_T ui32Free;
+       IMG_SIZE_T ui32LargestBlock;
+
+} PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM;
+
+
+#include "pvrmmap.h"
+typedef struct PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA_TAG
+{
+    PVRSRV_ERROR               eError;
+    
+    
+     IMG_UINT32                        ui32MMapOffset;
+
+    
+    IMG_UINT32                 ui32ByteOffset;
+
+    
+    IMG_UINT32                         ui32RealByteSize;
+
+    
+    IMG_UINT32                 ui32UserVAddr;
+
+} PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA_TAG
+{
+    PVRSRV_ERROR               eError;
+    
+    
+    IMG_BOOL                   bMUnmap;
+
+    
+    IMG_UINT32                 ui32UserVAddr;
+
+    
+    IMG_UINT32                 ui32RealByteSize;
+} PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA;
+typedef struct PVRSRV_BRIDGE_IN_GET_MISC_INFO_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       PVRSRV_MISC_INFO        sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_GET_MISC_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_MISC_INFO_TAG
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_MISC_INFO        sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_MISC_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       PVRSRV_MISC_INFO        sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO_TAG
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_MISC_INFO        sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_BOOL bIsCapturing;
+
+} PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING;
+
+typedef struct PVRSRV_BRIDGE_IN_GET_FB_STATS_TAG 
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_SIZE_T ui32Total;
+       IMG_SIZE_T ui32Available;
+
+} PVRSRV_BRIDGE_IN_GET_FB_STATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_SYS_PHYADDR         sSysPhysAddr;
+       IMG_UINT32                      uiSizeInBytes;
+
+} PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE_TAG
+{
+       IMG_PVOID                       pvUserAddr;
+       IMG_UINT32                      uiActualSize;
+       IMG_PVOID                       pvProcess;
+
+} PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_PVOID                       pvUserAddr;
+       IMG_PVOID                       pvProcess;
+
+} PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP_TAG
+{
+       IMG_PVOID                       *ppvTbl;
+       IMG_UINT32                      uiTblSize;
+
+} PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP;
+
+
+typedef struct PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_PVOID                       pvProcess;
+
+} PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS_TAG
+{
+       IMG_SYS_PHYADDR         sRegsPhysBase;                  
+       IMG_VOID                        *pvRegsBase;                    
+       IMG_PVOID                       pvProcess;
+       IMG_UINT32                      ulNoOfEntries;
+       IMG_PVOID                       pvTblLinAddr;
+
+} PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_PVOID                       pvProcess;
+       IMG_VOID                        *pvRegsBase;                    
+
+} PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS;
+
+typedef struct PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_UINT32                      ui32StatusAndMask;
+       PVRSRV_ERROR            eError;
+
+} PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT;
+
+typedef struct PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_BOOL                        bInitSuccesful;
+} PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+    IMG_UINT32 ui32Flags;
+    IMG_SIZE_T ui32Size;
+}PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM_TAG
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+}PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+}PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM_TAG
+{
+       PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM_TAG
+{
+       PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+       PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+       PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM_TAG
+{
+       PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+    IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR_TAG
+{
+    IMG_DEV_PHYADDR sPDDevPAddr;
+       PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAI_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE      hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN_TAG
+{
+       PVRSRV_EVENTOBJECT sEventObject;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN_TAG
+{
+       IMG_HANDLE hOSEvent;
+       PVRSRV_ERROR eError;
+} PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE_TAG
+{
+       PVRSRV_EVENTOBJECT sEventObject;
+       IMG_HANDLE hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE;
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ_TAG
+{
+       PVRSRV_ERROR eError;
+
+       IMG_HANDLE hKernelSyncInfoModObj;
+
+} PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hKernelSyncInfoModObj;
+       IMG_HANDLE hKernelSyncInfo;
+       IMG_UINT32 ui32ModifyFlags;
+
+} PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS_TAG
+{
+       PVRSRV_ERROR eError;
+
+       
+       IMG_UINT32 ui32ReadOpsPending;
+       IMG_UINT32 ui32WriteOpsPending;
+
+} PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hKernelSyncInfo;
+       IMG_UINT32 ui32Delta;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA;
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+
+       IMG_HANDLE hDevCookie;
+} PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO_TAG
+{
+       PVRSRV_ERROR eError;
+
+       IMG_HANDLE hKernelSyncInfo;
+} PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SYNC_INFO_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+
+       IMG_HANDLE hKernelSyncInfo;
+} PVRSRV_BRIDGE_IN_FREE_SYNC_INFO;
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/include/pvr_bridge_km.h b/drivers/staging/mrst/pvr/services4/include/pvr_bridge_km.h
new file mode 100644 (file)
index 0000000..7f82e93
--- /dev/null
@@ -0,0 +1,286 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_KM_H_
+#define __PVR_BRIDGE_KM_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined(__linux__)
+PVRSRV_ERROR LinuxBridgeInit(IMG_VOID);
+IMG_VOID LinuxBridgeDeInit(IMG_VOID);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+                                                                                                  PVRSRV_DEVICE_IDENTIFIER *psDevIdList);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM(IMG_UINT32                 uiDevIndex,
+                                                                                                       PVRSRV_DEVICE_TYPE      eDeviceType,
+                                                                                                       IMG_HANDLE                      *phDevCookie);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+                                                                                                        PVRSRV_QUEUE_INFO **ppsQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+                                                                                                       PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE                                    hDevCookie,
+                                                                                                                PVRSRV_PER_PROCESS_DATA        *psPerProc,
+                                                                                                                IMG_HANDLE                                     *phDevMemContext,
+                                                                                                                IMG_UINT32                                     *pui32ClientHeapCount,
+                                                                                                                PVRSRV_HEAP_INFO                       *psHeapInfo,
+                                                                                                                IMG_BOOL                                       *pbCreated,
+                                                                                                                IMG_BOOL                                       *pbShared);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+                                                                                                                 IMG_HANDLE hDevMemContext,
+                                                                                                                 IMG_BOOL *pbDestroyed);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE                              hDevCookie,
+                                                                                                                       IMG_HANDLE                      hDevMemContext,
+                                                                                                                       IMG_UINT32                      *pui32ClientHeapCount,
+                                                                                                                       PVRSRV_HEAP_INFO        *psHeapInfo,
+                                                                                                                       IMG_BOOL                        *pbShared
+                                       );
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE                                   hDevCookie,
+                                                                                                PVRSRV_PER_PROCESS_DATA        *psPerProc,
+                                                                                                IMG_HANDLE                                     hDevMemHeap,
+                                                                                                IMG_UINT32                                     ui32Flags,
+                                                                                                IMG_SIZE_T                                     ui32Size,
+                                                                                                IMG_SIZE_T                                     ui32Alignment,
+                                                                                                PVRSRV_KERNEL_MEM_INFO         **ppsMemInfo);
+
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+       #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+               (PVR_TRACE(("PVRSRVAllocDeviceMemKM(" #devCookie ", " #perProc ", " #devMemHeap ", " #flags ", " #size \
+                       ", " #alignment "," #memInfo "): " logStr " (size = 0x%;x)", size)),\
+                       _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo))
+#else
+       #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+                       _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE                     hDevCookie,
+                                                                                               PVRSRV_KERNEL_MEM_INFO  *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE                       hDevCookie,
+                                                                                               PVRSRV_KERNEL_MEM_INFO  *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMemKM(IMG_HANDLE           hDevMemHeap,
+                                                                                                                IMG_DEV_VIRTADDR       *psDevVAddr,
+                                                                                                                IMG_SIZE_T                     ui32Size,
+                                                                                                                IMG_SIZE_T                     ui32Alignment,
+                                                                                                                PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMemKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA      *psPerProc,
+                                                                                                 PVRSRV_KERNEL_MEM_INFO        *psSrcMemInfo,
+                                                                                                 IMG_HANDLE                            hDstDevMemHeap,
+                                                                                                 PVRSRV_KERNEL_MEM_INFO        **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE                             hDevCookie,
+                                                                                               PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                                                                               IMG_HANDLE                              hDevMemContext,
+                                                                                               IMG_SIZE_T                              ui32ByteSize,
+                                                                                               IMG_SIZE_T                              ui32PageOffset,
+                                                                                               IMG_BOOL                                bPhysContig,
+                                                                                               IMG_SYS_PHYADDR                 *psSysAddr,
+                                                                                               IMG_VOID                                *pvLinAddr,
+                                                                                               IMG_UINT32                              ui32Flags,
+                                                                                               PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS DeviceClass,
+                                                                IMG_UINT32 *pui32DevCount,
+                                                                IMG_UINT32 *pui32DevID );
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM(PVRSRV_PER_PROCESS_DATA      *psPerProc,
+                                                                 IMG_UINT32                            ui32DeviceID,
+                                                                 IMG_HANDLE                            hDevCookie,
+                                                                 IMG_HANDLE                            *phDeviceKM);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM(IMG_HANDLE hDeviceKM,
+                                                                  IMG_UINT32 *pui32Count,
+                                                                  DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM(IMG_HANDLE hDeviceKM,
+                                                               DISPLAY_FORMAT *psFormat,
+                                                               IMG_UINT32 *pui32Count,
+                                                               DISPLAY_DIMS *psDim);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(IMG_HANDLE hDeviceKM,
+                                                                          IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM(IMG_HANDLE hDeviceKM,
+                                                          DISPLAY_INFO *psDisplayInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                                                          IMG_HANDLE                           hDeviceKM,
+                                                                          IMG_UINT32                           ui32Flags,
+                                                                          DISPLAY_SURF_ATTRIBUTES      *psDstSurfAttrib,
+                                                                          DISPLAY_SURF_ATTRIBUTES      *psSrcSurfAttrib,
+                                                                          IMG_UINT32                           ui32BufferCount,
+                                                                          IMG_UINT32                           ui32OEMFlags,
+                                                                          IMG_HANDLE                           *phSwapChain,
+                                                                          IMG_UINT32                           *pui32SwapChainID);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE     hSwapChain);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE   hDeviceKM,
+                                                                 IMG_HANDLE    hSwapChain,
+                                                                 IMG_RECT      *psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE   hDeviceKM,
+                                                                 IMG_HANDLE    hSwapChain,
+                                                                 IMG_RECT      *psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE      hDeviceKM,
+                                                                          IMG_HANDLE   hSwapChain,
+                                                                          IMG_UINT32   ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE      hDeviceKM,
+                                                                       IMG_HANDLE              hSwapChain,
+                                                                       IMG_UINT32              ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE   hDeviceKM,
+                                                                 IMG_HANDLE    hSwapChain,
+                                                                 IMG_UINT32    *pui32BufferCount,
+                                                                 IMG_HANDLE    *phBuffer);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
+                                                                       IMG_HANDLE      hBuffer,
+                                                                       IMG_UINT32      ui32SwapInterval,
+                                                                       IMG_HANDLE      hPrivateTag,
+                                                                       IMG_UINT32      ui32ClipRectCount,
+                                                                       IMG_RECT        *psClipRect,
+                                                                       PVRSRV_PER_PROCESS_DATA *psPerProc);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+                                                                       IMG_HANDLE      hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM(PVRSRV_PER_PROCESS_DATA      *psPerProc,
+                                                                 IMG_UINT32                            ui32DeviceID,
+                                                                 IMG_HANDLE                            hDevCookie,
+                                                                 IMG_HANDLE                            *phDeviceKM);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM(IMG_HANDLE      hDeviceKM,
+                                                          BUFFER_INFO  *psBufferInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM(IMG_HANDLE    hDeviceKM,
+                                                                IMG_UINT32     ui32BufferIndex,
+                                                                IMG_HANDLE     *phBuffer);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                                                                                          IMG_HANDLE                           hDevMemContext,
+                                                                                                          IMG_HANDLE                           hDeviceClassBuffer,
+                                                                                                          PVRSRV_KERNEL_MEM_INFO       **ppsMemInfo,
+                                                                                                          IMG_HANDLE                           *phOSMapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+                                                                                                  IMG_SIZE_T *pui32Total,
+                                                                                                  IMG_SIZE_T *pui32Free,
+                                                                                                  IMG_SIZE_T *pui32LargestBlock);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE                                     hDevCookie,
+                                                                                               IMG_HANDLE                                      hDevMemContext,
+                                                                                               PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA   *psPerProc,
+                                                        IMG_UINT32                             ui32Flags,
+                                                        IMG_SIZE_T                             ui32Size,
+                                                        PVRSRV_KERNEL_MEM_INFO         **ppsKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/include/pvrmmap.h b/drivers/staging/mrst/pvr/services4/include/pvrmmap.h
new file mode 100644 (file)
index 0000000..7270f54
--- /dev/null
@@ -0,0 +1,36 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PVRMMAP_H__
+#define __PVRMMAP_H__
+
+PVRSRV_ERROR PVRPMapKMem(IMG_HANDLE hModule, IMG_VOID **ppvLinAddr, IMG_VOID *pvLinAddrKM, IMG_HANDLE *phMappingInfo, IMG_HANDLE hMHandle);
+
+
+IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_HANDLE hMappingInfo, IMG_HANDLE hMHandle);
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/include/pvrsrv_errors.h b/drivers/staging/mrst/pvr/services4/include/pvrsrv_errors.h
new file mode 100644 (file)
index 0000000..56c7184
--- /dev/null
@@ -0,0 +1,264 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined (__PVRSRV_ERRORS_H__)
+#define __PVRSRV_ERRORS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+       switch (eError)
+       {
+               case PVRSRV_OK:                                                                 return "No Errors";
+               case PVRSRV_ERROR_OUT_OF_MEMORY:                                return "PVRSRV_ERROR_OUT_OF_MEMORY - Unable to allocate required memory";
+               case PVRSRV_ERROR_TOO_FEW_BUFFERS:                              return "PVRSRV_ERROR_TOO_FEW_BUFFERS";
+               case PVRSRV_ERROR_INVALID_PARAMS:                               return "PVRSRV_ERROR_INVALID_PARAMS";
+               case PVRSRV_ERROR_INIT_FAILURE:                                 return "PVRSRV_ERROR_INIT_FAILURE";
+               case PVRSRV_ERROR_CANT_REGISTER_CALLBACK:               return "PVRSRV_ERROR_CANT_REGISTER_CALLBACK";
+               case PVRSRV_ERROR_INVALID_DEVICE:                               return "PVRSRV_ERROR_INVALID_DEVICE";
+               case PVRSRV_ERROR_NOT_OWNER:                                    return "PVRSRV_ERROR_NOT_OWNER";
+               case PVRSRV_ERROR_BAD_MAPPING:                                  return "PVRSRV_ERROR_BAD_MAPPING";
+               case PVRSRV_ERROR_TIMEOUT:                                              return "PVRSRV_ERROR_TIMEOUT";
+               case PVRSRV_ERROR_FLIP_CHAIN_EXISTS:                    return "PVRSRV_ERROR_FLIP_CHAIN_EXISTS";
+               case PVRSRV_ERROR_INVALID_SWAPINTERVAL:                 return "PVRSRV_ERROR_INVALID_SWAPINTERVAL";
+               case PVRSRV_ERROR_SCENE_INVALID:                                return "PVRSRV_ERROR_SCENE_INVALID";
+               case PVRSRV_ERROR_STREAM_ERROR:                                 return "PVRSRV_ERROR_STREAM_ERROR";
+               case PVRSRV_ERROR_FAILED_DEPENDENCIES:                  return "PVRSRV_ERROR_FAILED_DEPENDENCIES";
+               case PVRSRV_ERROR_CMD_NOT_PROCESSED:                    return "PVRSRV_ERROR_CMD_NOT_PROCESSED";
+               case PVRSRV_ERROR_CMD_TOO_BIG:                                  return "PVRSRV_ERROR_CMD_TOO_BIG";
+               case PVRSRV_ERROR_DEVICE_REGISTER_FAILED:               return "PVRSRV_ERROR_DEVICE_REGISTER_FAILED";
+               case PVRSRV_ERROR_TOOMANYBUFFERS:                               return "PVRSRV_ERROR_TOOMANYBUFFERS";
+               case PVRSRV_ERROR_NOT_SUPPORTED:                                return "PVRSRV_ERROR_NOT_SUPPORTED - fix";
+               case PVRSRV_ERROR_PROCESSING_BLOCKED:                   return "PVRSRV_ERROR_PROCESSING_BLOCKED";
+
+               case PVRSRV_ERROR_CANNOT_FLUSH_QUEUE:                   return "PVRSRV_ERROR_CANNOT_FLUSH_QUEUE";
+               case PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE:               return "PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE";
+               case PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS:             return "PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS";
+               case PVRSRV_ERROR_RETRY:                                                return "PVRSRV_ERROR_RETRY";
+
+               case PVRSRV_ERROR_DDK_VERSION_MISMATCH:                 return "PVRSRV_ERROR_DDK_VERSION_MISMATCH";
+               case PVRSRV_ERROR_BUILD_MISMATCH:                               return "PVRSRV_ERROR_BUILD_MISMATCH";
+               case PVRSRV_ERROR_CORE_REVISION_MISMATCH:               return "PVRSRV_ERROR_CORE_REVISION_MISMATCH";
+
+               case PVRSRV_ERROR_UPLOAD_TOO_BIG:                               return "PVRSRV_ERROR_UPLOAD_TOO_BIG";
+
+               case PVRSRV_ERROR_INVALID_FLAGS:                                return "PVRSRV_ERROR_INVALID_FLAGS";
+               case PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS:   return "PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS";
+
+               case PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY:               return "PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY";
+               case PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR:                 return "PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR";
+               case PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED:                return "PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED";
+
+               case PVRSRV_ERROR_BRIDGE_CALL_FAILED:                   return "PVRSRV_ERROR_BRIDGE_CALL_FAILED";
+               case PVRSRV_ERROR_IOCTL_CALL_FAILED:                    return "PVRSRV_ERROR_IOCTL_CALL_FAILED";
+
+               case PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND:                return "PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND";
+               case PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND:              return "PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND";
+               case PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT:return "PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT";
+
+               case PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND:                 return "PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND";
+               case PVRSRV_ERROR_PCI_CALL_FAILED:                              return "PVRSRV_ERROR_PCI_CALL_FAILED";
+               case PVRSRV_ERROR_PCI_REGION_TOO_SMALL:                 return "PVRSRV_ERROR_PCI_REGION_TOO_SMALL";
+               case PVRSRV_ERROR_PCI_REGION_UNAVAILABLE:               return "PVRSRV_ERROR_PCI_REGION_UNAVAILABLE";
+               case PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH:             return "PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH";
+
+               case PVRSRV_ERROR_REGISTER_BASE_NOT_SET:                return "PVRSRV_ERROR_REGISTER_BASE_NOT_SET";
+
+               case PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM:             return "PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM";
+               case PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY:    return "PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY";
+               case PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC:  return "PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC";
+               case PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR:              return "PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR";
+
+               case PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY:  return "PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY";
+               case PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY:   return "PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY";
+
+               case PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES:                return "PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES";
+               case PVRSRV_ERROR_FAILED_TO_FREE_PAGES:                 return "PVRSRV_ERROR_FAILED_TO_FREE_PAGES";
+               case PVRSRV_ERROR_FAILED_TO_COPY_PAGES:                 return "PVRSRV_ERROR_FAILED_TO_COPY_PAGES";
+               case PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES:                 return "PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES";
+               case PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES:               return "PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES";
+               case PVRSRV_ERROR_STILL_MAPPED:                                 return "PVRSRV_ERROR_STILL_MAPPED";
+               case PVRSRV_ERROR_MAPPING_NOT_FOUND:                    return "PVRSRV_ERROR_MAPPING_NOT_FOUND";
+               case PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT:   return "PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT";
+               case PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE:             return "PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE";
+
+               case PVRSRV_ERROR_INVALID_SEGMENT_BLOCK:                return "PVRSRV_ERROR_INVALID_SEGMENT_BLOCK";
+               case PVRSRV_ERROR_INVALID_SGXDEVDATA:                   return "PVRSRV_ERROR_INVALID_SGXDEVDATA";
+               case PVRSRV_ERROR_INVALID_DEVINFO:                              return "PVRSRV_ERROR_INVALID_DEVINFO";
+               case PVRSRV_ERROR_INVALID_MEMINFO:                              return "PVRSRV_ERROR_INVALID_MEMINFO";
+               case PVRSRV_ERROR_INVALID_MISCINFO:                             return "PVRSRV_ERROR_INVALID_MISCINFO";
+               case PVRSRV_ERROR_UNKNOWN_IOCTL:                                return "PVRSRV_ERROR_UNKNOWN_IOCTL";
+               case PVRSRV_ERROR_INVALID_CONTEXT:                              return "PVRSRV_ERROR_INVALID_CONTEXT";
+               case PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT:    return "PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT";
+               case PVRSRV_ERROR_INVALID_HEAP:                                 return "PVRSRV_ERROR_INVALID_HEAP";
+               case PVRSRV_ERROR_INVALID_KERNELINFO:                   return "PVRSRV_ERROR_INVALID_KERNELINFO";
+               case PVRSRV_ERROR_UNKNOWN_POWER_STATE:                  return "PVRSRV_ERROR_UNKNOWN_POWER_STATE";
+               case PVRSRV_ERROR_INVALID_HANDLE_TYPE:                  return "PVRSRV_ERROR_INVALID_HANDLE_TYPE";
+               case PVRSRV_ERROR_INVALID_WRAP_TYPE:                    return "PVRSRV_ERROR_INVALID_WRAP_TYPE";
+               case PVRSRV_ERROR_INVALID_PHYS_ADDR:                    return "PVRSRV_ERROR_INVALID_PHYS_ADDR";
+               case PVRSRV_ERROR_INVALID_CPU_ADDR:                             return "PVRSRV_ERROR_INVALID_CPU_ADDR";
+               case PVRSRV_ERROR_INVALID_HEAPINFO:                             return "PVRSRV_ERROR_INVALID_HEAPINFO";
+               case PVRSRV_ERROR_INVALID_PERPROC:                              return "PVRSRV_ERROR_INVALID_PERPROC";
+               case PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO:  return "PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO";
+               case PVRSRV_ERROR_INVALID_MAP_REQUEST:                  return "PVRSRV_ERROR_INVALID_MAP_REQUEST";
+               case PVRSRV_ERROR_INVALID_UNMAP_REQUEST:                return "PVRSRV_ERROR_INVALID_UNMAP_REQUEST";
+               case PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP:  return "PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP";
+               case PVRSRV_ERROR_MAPPING_STILL_IN_USE:                 return "PVRSRV_ERROR_MAPPING_STILL_IN_USE";
+
+               case PVRSRV_ERROR_EXCEEDED_HW_LIMITS:                   return "PVRSRV_ERROR_EXCEEDED_HW_LIMITS";
+               case PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED:  return "PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED";
+
+               case PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA:return "PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA";
+               case PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT:               return "PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT";
+               case PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT:               return "PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT";
+               case PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT:             return "PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT";
+               case PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT:              return "PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT";
+               case PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD:              return "PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD";
+               case PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD:               return "PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD";
+               case PVRSRV_ERROR_THREAD_READ_ERROR:                    return "PVRSRV_ERROR_THREAD_READ_ERROR";
+               case PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER:return "PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER";
+               case PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR:                return "PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR";
+               case PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR:              return "PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR";
+               case PVRSRV_ERROR_ISR_ALREADY_INSTALLED:                return "PVRSRV_ERROR_ISR_ALREADY_INSTALLED";
+               case PVRSRV_ERROR_ISR_NOT_INSTALLED:                    return "PVRSRV_ERROR_ISR_NOT_INSTALLED";
+               case PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT:return "PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT";
+               case PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO:              return "PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO";
+               case PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT:  return "PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT";
+               case PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES:             return "PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES";
+               case PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT:   return "PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT";
+               case PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE:  return "PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE";
+
+               case PVRSRV_ERROR_INVALID_CCB_COMMAND:                  return "PVRSRV_ERROR_INVALID_CCB_COMMAND";
+
+               case PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE:              return "PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE";
+               case PVRSRV_ERROR_INVALID_LOCK_ID:                              return "PVRSRV_ERROR_INVALID_LOCK_ID";
+               case PVRSRV_ERROR_RESOURCE_NOT_LOCKED:                  return "PVRSRV_ERROR_RESOURCE_NOT_LOCKED";
+
+               case PVRSRV_ERROR_FLIP_FAILED:                                  return "PVRSRV_ERROR_FLIP_FAILED";
+               case PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED:               return "PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED";
+
+               case PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE:    return "PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE";
+
+               case PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED: return "PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED";
+               case PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG:                 return "PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG";
+               case PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG:    return "PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG";
+               case PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG:              return "PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG";
+
+               case PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID:    return "PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID";
+
+               case PVRSRV_ERROR_BLIT_SETUP_FAILED:                    return "PVRSRV_ERROR_BLIT_SETUP_FAILED";
+
+               case PVRSRV_ERROR_PDUMP_NOT_AVAILABLE:                  return "PVRSRV_ERROR_PDUMP_NOT_AVAILABLE";
+               case PVRSRV_ERROR_PDUMP_BUFFER_FULL:                    return "PVRSRV_ERROR_PDUMP_BUFFER_FULL";
+               case PVRSRV_ERROR_PDUMP_BUF_OVERFLOW:                   return "PVRSRV_ERROR_PDUMP_BUF_OVERFLOW";
+               case PVRSRV_ERROR_PDUMP_NOT_ACTIVE:                             return "PVRSRV_ERROR_PDUMP_NOT_ACTIVE";
+               case PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES:return "PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES";
+
+               case PVRSRV_ERROR_MUTEX_DESTROY_FAILED:                 return "PVRSRV_ERROR_MUTEX_DESTROY_FAILED";
+               case PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR:    return "PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR";
+
+               case PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE:    return "PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE";
+               case PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND:return "PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND";
+
+               case PVRSRV_ERROR_PROCESS_NOT_INITIALISED:              return "PVRSRV_ERROR_PROCESS_NOT_INITIALISED";
+               case PVRSRV_ERROR_PROCESS_NOT_FOUND:                    return "PVRSRV_ERROR_PROCESS_NOT_FOUND";
+               case PVRSRV_ERROR_SRV_CONNECT_FAILED:                   return "PVRSRV_ERROR_SRV_CONNECT_FAILED";
+               case PVRSRV_ERROR_SRV_DISCONNECT_FAILED:                return "PVRSRV_ERROR_SRV_DISCONNECT_FAILED";
+               case PVRSRV_ERROR_DEINT_PHASE_FAILED:                   return "PVRSRV_ERROR_DEINT_PHASE_FAILED";
+               case PVRSRV_ERROR_INIT2_PHASE_FAILED:                   return "PVRSRV_ERROR_INIT2_PHASE_FAILED";
+
+               case PVRSRV_ERROR_NO_DC_DEVICES_FOUND:                  return "PVRSRV_ERROR_NO_DC_DEVICES_FOUND";
+               case PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE:             return "PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE";
+               case PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE:              return "PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE";
+               case PVRSRV_ERROR_NO_DEVICEDATA_FOUND:                  return "PVRSRV_ERROR_NO_DEVICEDATA_FOUND";
+               case PVRSRV_ERROR_NO_DEVICENODE_FOUND:                  return "PVRSRV_ERROR_NO_DEVICENODE_FOUND";
+               case PVRSRV_ERROR_NO_CLIENTNODE_FOUND:                  return "PVRSRV_ERROR_NO_CLIENTNODE_FOUND";
+               case PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE:              return "PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE";
+
+               case PVRSRV_ERROR_UNABLE_TO_INIT_TASK:                  return "PVRSRV_ERROR_UNABLE_TO_INIT_TASK";
+               case PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK:              return "PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK";
+               case PVRSRV_ERROR_UNABLE_TO_KILL_TASK:                  return "PVRSRV_ERROR_UNABLE_TO_KILL_TASK";
+
+               case PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER:               return "PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER";
+               case PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER:              return "PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER";
+               case PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER:               return "PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER";
+
+               case PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT:                 return "PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT";
+               case PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION:             return "PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION";
+
+               case PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE:    return "PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE";
+               case PVRSRV_ERROR_HANDLE_NOT_ALLOCATED:                 return "PVRSRV_ERROR_HANDLE_NOT_ALLOCATED";
+               case PVRSRV_ERROR_HANDLE_TYPE_MISMATCH:                 return "PVRSRV_ERROR_HANDLE_TYPE_MISMATCH";
+               case PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE:                 return "PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE";
+               case PVRSRV_ERROR_HANDLE_NOT_SHAREABLE:                 return "PVRSRV_ERROR_HANDLE_NOT_SHAREABLE";
+               case PVRSRV_ERROR_HANDLE_NOT_FOUND:                             return "PVRSRV_ERROR_HANDLE_NOT_FOUND";
+               case PVRSRV_ERROR_INVALID_SUBHANDLE:                    return "PVRSRV_ERROR_INVALID_SUBHANDLE";
+               case PVRSRV_ERROR_HANDLE_BATCH_IN_USE:                  return "PVRSRV_ERROR_HANDLE_BATCH_IN_USE";
+               case PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE:  return "PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE";
+
+               case PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE:  return "PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE";
+               case PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED:return "PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED";
+
+               case PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE:    return "PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE";
+               case PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP:    return "PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP";
+
+               case PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE:    return "PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE";
+
+               case PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE:  return "PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE";
+               case PVRSRV_ERROR_INVALID_DEVICEID:                             return "PVRSRV_ERROR_INVALID_DEVICEID";
+               case PVRSRV_ERROR_DEVICEID_NOT_FOUND:                   return "PVRSRV_ERROR_DEVICEID_NOT_FOUND";
+
+               case PVRSRV_ERROR_MEMORY_TEST_FAILED:                   return "PVRSRV_ERROR_MEMORY_TEST_FAILED";
+               case PVRSRV_ERROR_CPUPADDR_TEST_FAILED:                 return "PVRSRV_ERROR_CPUPADDR_TEST_FAILED";
+               case PVRSRV_ERROR_COPY_TEST_FAILED:                             return "PVRSRV_ERROR_COPY_TEST_FAILED";
+
+               case PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED:    return "PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED";
+
+               case PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK:              return "PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK";
+               case PVRSRV_ERROR_CLOCK_REQUEST_FAILED:                 return "PVRSRV_ERROR_CLOCK_REQUEST_FAILED";
+               case PVRSRV_ERROR_DISABLE_CLOCK_FAILURE:                return "PVRSRV_ERROR_DISABLE_CLOCK_FAILURE";
+               case PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE:             return "PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE";
+               case PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE:   return "PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE";
+               case PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK:               return "PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK";
+               case PVRSRV_ERROR_UNABLE_TO_GET_CLOCK:                  return "PVRSRV_ERROR_UNABLE_TO_GET_CLOCK";
+               case PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK:   return "PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK";
+               case PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK:   return "PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK";
+
+               case PVRSRV_ERROR_UNKNOWN_SGL_ERROR:                    return "PVRSRV_ERROR_UNKNOWN_SGL_ERROR";
+           case PVRSRV_ERROR_BAD_SYNC_STATE:               return "PVRSRV_ERROR_BAD_SYNC_STATE";
+
+               case PVRSRV_ERROR_FORCE_I32:                                    return "PVRSRV_ERROR_FORCE_I32";
+
+               default:
+                       return "Unknown PVRSRV error number";
+       }
+
+#if defined (__cplusplus)
+}
+#endif
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/include/servicesint.h b/drivers/staging/mrst/pvr/services4/include/servicesint.h
new file mode 100644 (file)
index 0000000..aa8d745
--- /dev/null
@@ -0,0 +1,293 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined (__SERVICESINT_H__)
+#define __SERVICESINT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <linux/types.h>
+
+#include "services.h"
+#include "sysinfo.h"
+
+#define HWREC_DEFAULT_TIMEOUT  (500)
+
+#define DRIVERNAME_MAXLENGTH   (100)
+
+#define        ALIGNSIZE(size, alignshift)     (((size) + ((1UL << (alignshift))-1)) & ~((1UL << (alignshift))-1))
+
+#ifndef MAX
+#define MAX(a,b)                                       max(a,b)
+#endif
+#ifndef MIN
+#define MIN(a,b)                                       min(a,b)
+#endif
+
+
+typedef enum _PVRSRV_MEMTYPE_
+{
+       PVRSRV_MEMTYPE_UNKNOWN          = 0,
+       PVRSRV_MEMTYPE_DEVICE           = 1,
+       PVRSRV_MEMTYPE_DEVICECLASS      = 2,
+       PVRSRV_MEMTYPE_WRAPPED          = 3,
+       PVRSRV_MEMTYPE_MAPPED           = 4,
+} PVRSRV_MEMTYPE;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_
+{
+       
+       IMG_PVOID                               pvLinAddrKM;
+
+       
+       IMG_DEV_VIRTADDR                sDevVAddr;
+
+       
+       IMG_UINT32                              ui32Flags;
+
+       
+       IMG_SIZE_T                              ui32AllocSize;
+
+       
+       PVRSRV_MEMBLK                   sMemBlk;
+
+       
+       IMG_PVOID                               pvSysBackupBuffer;
+
+       
+       IMG_UINT32                              ui32RefCount;
+
+       
+       IMG_BOOL                                bPendingFree;
+
+
+#if defined(SUPPORT_MEMINFO_IDS)
+       #if !defined(USE_CODE)
+       
+       IMG_UINT64                              ui64Stamp;
+       #else 
+       IMG_UINT32                              dummy1;
+       IMG_UINT32                              dummy2;
+       #endif 
+#endif 
+
+       
+       struct _PVRSRV_KERNEL_SYNC_INFO_        *psKernelSyncInfo;
+
+       PVRSRV_MEMTYPE                          memType;
+} PVRSRV_KERNEL_MEM_INFO;
+
+
+typedef struct _PVRSRV_KERNEL_SYNC_INFO_
+{
+       
+       PVRSRV_SYNC_DATA                *psSyncData;
+
+       
+       IMG_DEV_VIRTADDR                sWriteOpsCompleteDevVAddr;
+
+       
+       IMG_DEV_VIRTADDR                sReadOpsCompleteDevVAddr;
+
+       
+       PVRSRV_KERNEL_MEM_INFO  *psSyncDataMemInfoKM;
+
+       
+       
+       IMG_UINT32              ui32RefCount;
+
+       
+       IMG_HANDLE hResItem;
+
+#ifdef CONFIG_PVR_TRACE_CMD
+       struct list_head        link;
+       unsigned long           counter_digest;
+#endif
+} PVRSRV_KERNEL_SYNC_INFO;
+
+typedef struct _PVRSRV_DEVICE_SYNC_OBJECT_
+{
+       
+       IMG_UINT32                      ui32ReadOpsPendingVal;
+       IMG_DEV_VIRTADDR        sReadOpsCompleteDevVAddr;
+       IMG_UINT32                      ui32WriteOpsPendingVal;
+       IMG_DEV_VIRTADDR        sWriteOpsCompleteDevVAddr;
+} PVRSRV_DEVICE_SYNC_OBJECT;
+
+typedef struct _PVRSRV_SYNC_OBJECT
+{
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfoKM;
+       IMG_UINT32                              ui32WriteOpsPending;
+       IMG_UINT32                              ui32ReadOpsPending;
+
+}PVRSRV_SYNC_OBJECT, *PPVRSRV_SYNC_OBJECT;
+
+typedef struct _PVRSRV_COMMAND
+{
+       IMG_SIZE_T                      ui32CmdSize;            
+       IMG_UINT32                      ui32DevIndex;           
+       IMG_UINT32                      CommandType;            
+       IMG_UINT32                      ui32DstSyncCount;       
+       IMG_UINT32                      ui32SrcSyncCount;       
+       PVRSRV_SYNC_OBJECT      *psDstSync;                     
+       PVRSRV_SYNC_OBJECT      *psSrcSync;                     
+       IMG_SIZE_T                      ui32DataSize;           
+       IMG_UINT32                      ui32ProcessID;          
+       IMG_VOID                        *pvData;                        
+}PVRSRV_COMMAND, *PPVRSRV_COMMAND;
+
+
+typedef struct _PVRSRV_QUEUE_INFO_
+{
+       IMG_VOID                        *pvLinQueueKM;                  
+       IMG_VOID                        *pvLinQueueUM;                  
+       volatile IMG_SIZE_T     ui32ReadOffset;                 
+       volatile IMG_SIZE_T     ui32WriteOffset;                
+       IMG_UINT32                      *pui32KickerAddrKM;             
+       IMG_UINT32                      *pui32KickerAddrUM;             
+       IMG_SIZE_T                      ui32QueueSize;                  
+
+       IMG_UINT32                      ui32ProcessID;                  
+
+       IMG_HANDLE                      hMemBlock[2];
+
+       struct _PVRSRV_QUEUE_INFO_ *psNextKM;           
+}PVRSRV_QUEUE_INFO;
+
+typedef PVRSRV_ERROR (*PFN_INSERT_CMD) (PVRSRV_QUEUE_INFO*,
+                                                                               PVRSRV_COMMAND**,
+                                                                               IMG_UINT32,
+                                                                               IMG_UINT16,
+                                                                               IMG_UINT32,
+                                                                               PVRSRV_KERNEL_SYNC_INFO*[],
+                                                                               IMG_UINT32,
+                                                                               PVRSRV_KERNEL_SYNC_INFO*[],
+                                                                               IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SUBMIT_CMD) (PVRSRV_QUEUE_INFO*, PVRSRV_COMMAND*, IMG_BOOL);
+
+
+typedef struct PVRSRV_DEVICECLASS_BUFFER_TAG
+{
+       PFN_GET_BUFFER_ADDR             pfnGetBufferAddr;
+       IMG_HANDLE                              hDevMemContext;
+       IMG_HANDLE                              hExtDevice;
+       IMG_HANDLE                              hExtBuffer;
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+} PVRSRV_DEVICECLASS_BUFFER;
+
+
+typedef struct PVRSRV_CLIENT_DEVICECLASS_INFO_TAG
+{
+       IMG_HANDLE hDeviceKM;
+       IMG_HANDLE      hServices;
+} PVRSRV_CLIENT_DEVICECLASS_INFO;
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetWriteOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetWriteOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+       IMG_UINT32 ui32WriteOpsPending;
+
+       if(bIsReadOp)
+       {
+               ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+       }
+       else
+       {
+               
+
+
+               ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+       }
+
+       return ui32WriteOpsPending;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetReadOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetReadOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+       IMG_UINT32 ui32ReadOpsPending;
+
+       if(bIsReadOp)
+       {
+               ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+       }
+       else
+       {
+               ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+       }
+
+       return ui32ReadOpsPending;
+}
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVQueueCommand(IMG_HANDLE hQueueInfo,
+                                                               PVRSRV_COMMAND *psCommand);
+
+
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVGetMMUContextPDDevPAddr(const PVRSRV_CONNECTION *psConnection,
+                              IMG_HANDLE hDevMemContext,
+                              IMG_DEV_PHYADDR *sPDDevPAddr);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVAllocSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+                                               IMG_UINT32 ui32Flags,
+                                               IMG_SIZE_T ui32Size,
+                                               PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVFreeSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+                                          PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVUnrefSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+                        PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVMapMemInfoMem(const PVRSRV_CONNECTION *psConnection,
+                    IMG_HANDLE hKernelMemInfo,
+                    PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+PVRSRV_KERNEL_MEM_INFO* PVRSRVGetMapMemInfo(IMG_VOID *psMap);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/include/sgx_bridge.h b/drivers/staging/mrst/pvr/services4/include/sgx_bridge.h
new file mode 100644 (file)
index 0000000..10e5919
--- /dev/null
@@ -0,0 +1,466 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_H__)
+#define __SGX_BRIDGE_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "pvr_bridge.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#define PVRSRV_BRIDGE_SGX_CMD_BASE (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+#define PVRSRV_BRIDGE_SGX_GETCLIENTINFO                        PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+0)
+#define PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO            PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+1)
+#define PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO   PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+2)
+#define PVRSRV_BRIDGE_SGX_DOKICK                               PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+3)
+#define PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR              PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+4)
+#define PVRSRV_BRIDGE_SGX_READREGISTRYDWORD            PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+5)
+
+#define PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE   PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+9)
+
+#define PVRSRV_BRIDGE_SGX_GETMMUPDADDR                 PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+10)  
+
+#if defined(TRANSFER_QUEUE)
+#define PVRSRV_BRIDGE_SGX_SUBMITTRANSFER                       PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+13)
+#endif
+#define PVRSRV_BRIDGE_SGX_GETMISCINFO                          PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+14)
+#define PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT                      PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+15)
+#define PVRSRV_BRIDGE_SGX_DEVINITPART2                         PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+16)
+
+#define PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC                     PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+17)
+#define PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC                    PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+18)
+#define PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC                      PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+19)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT   PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+20)
+#define PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET       PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+21)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+22)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_BRIDGE_SGX_SUBMIT2D                                     PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+23)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT       PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+24)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT     PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+25)
+#endif
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+26)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT       PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+27)
+
+#define PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES              PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+#define PVRSRV_BRIDGE_SGX_READ_HWPERF_CB                       PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+30)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY           PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+31)
+#define PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+32)
+#define PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS      PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+33)
+#define PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+34)
+#define PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB                               PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+#define PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM                                        PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+36)
+#endif
+
+
+
+#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+36)
+
+typedef struct PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevMemHeap;
+       IMG_DEV_VIRTADDR sDevVAddr;
+}PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR;
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR
+{
+       PVRSRV_ERROR            eError;
+       IMG_DEV_PHYADDR         DevPAddr;
+       IMG_CPU_PHYADDR         CpuPAddr;
+}PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+       IMG_HANDLE                              hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR_TAG
+{
+       IMG_DEV_PHYADDR                 sPDDevPAddr;
+       PVRSRV_ERROR                    eError;
+}PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR;
+
+typedef struct PVRSRV_BRIDGE_IN_GETCLIENTINFO_TAG
+{
+       IMG_UINT32                                      ui32BridgeFlags; 
+       IMG_HANDLE                                      hDevCookie;
+}PVRSRV_BRIDGE_IN_GETCLIENTINFO;
+
+typedef struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO_TAG
+{
+       SGX_INTERNAL_DEVINFO    sSGXInternalDevInfo;
+       PVRSRV_ERROR                            eError;
+}PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+}PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO;
+
+typedef struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO_TAG
+{
+       SGX_CLIENT_INFO         sClientInfo;
+       PVRSRV_ERROR                    eError;
+}PVRSRV_BRIDGE_OUT_GETCLIENTINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+       SGX_CLIENT_INFO         sClientInfo;
+}PVRSRV_BRIDGE_IN_RELEASECLIENTINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_ISPBREAKPOLL_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+}PVRSRV_BRIDGE_IN_ISPBREAKPOLL;
+
+typedef struct PVRSRV_BRIDGE_IN_DOKICK_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+       SGX_CCB_KICK                    sCCBKick;
+}PVRSRV_BRIDGE_IN_DOKICK;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+}PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+       PVRSRV_TRANSFER_SGX_KICK                        sKick;
+}PVRSRV_BRIDGE_IN_SUBMITTRANSFER;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct PVRSRV_BRIDGE_IN_SUBMIT2D_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+       PVRSRV_2D_SGX_KICK                              sKick;
+} PVRSRV_BRIDGE_IN_SUBMIT2D;
+#endif
+#endif
+
+typedef struct PVRSRV_BRIDGE_IN_READREGDWORD_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+    IMG_PCHAR                          pszKey;
+    IMG_PCHAR                          pszValue;
+}PVRSRV_BRIDGE_IN_READREGDWORD;
+
+typedef struct PVRSRV_BRIDGE_OUT_READREGDWORD_TAG
+{
+       PVRSRV_ERROR    eError;
+       IMG_UINT32              ui32Data;
+}PVRSRV_BRIDGE_OUT_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO_TAG
+{
+       IMG_UINT32              ui32BridgeFlags; 
+       IMG_HANDLE              hDevCookie;
+       SGX_MISC_INFO   *psMiscInfo;
+}PVRSRV_BRIDGE_IN_SGXGETMISCINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT_TAG
+{
+       IMG_UINT32              ui32BridgeFlags; 
+       IMG_HANDLE              hDevCookie;
+}PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT_TAG
+{
+       PVRSRV_ERROR                    eError;
+       SGX_BRIDGE_INFO_FOR_SRVINIT     sInitInfo;
+}PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2_TAG
+{
+       IMG_UINT32              ui32BridgeFlags; 
+       IMG_HANDLE              hDevCookie;
+       SGX_BRIDGE_INIT_INFO    sInitInfo;
+}PVRSRV_BRIDGE_IN_SGXDEVINITPART2;
+
+typedef struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE_TAG
+{
+       IMG_UINT32                              ui32BridgeFlags; 
+       IMG_HANDLE                              hDevCookie;
+       IMG_HANDLE                              hKernSyncInfo;
+       IMG_BOOL                                bWaitForComplete;
+}PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE;
+
+
+#define PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS 10
+
+typedef struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_BOOL bLockOnFailure;
+       IMG_UINT32 ui32TotalPBSize;
+}PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC_TAG
+{
+       IMG_HANDLE hKernelMemInfo;
+       IMG_HANDLE hSharedPBDesc;
+       IMG_HANDLE hSharedPBDescKernelMemInfoHandle;
+       IMG_HANDLE hHWPBDescKernelMemInfoHandle;
+       IMG_HANDLE hBlockKernelMemInfoHandle;
+       IMG_HANDLE hHWBlockKernelMemInfoHandle;
+       IMG_HANDLE ahSharedPBDescSubKernelMemInfoHandles[PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS];
+       IMG_UINT32 ui32SharedPBDescSubKernelMemInfoHandlesCount;
+       PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC_TAG
+{
+       PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_HANDLE hSharedPBDescKernelMemInfo;
+       IMG_HANDLE hHWPBDescKernelMemInfo;
+       IMG_HANDLE hBlockKernelMemInfo;
+       IMG_HANDLE hHWBlockKernelMemInfo;
+       IMG_UINT32 ui32TotalPBSize;
+       IMG_HANDLE *phKernelMemInfoHandles;
+       IMG_UINT32 ui32KernelMemInfoHandlesCount;
+}PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC;
+
+
+#ifdef PDUMP
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       SGX_KICKTA_DUMP_BUFFER *psBufferArray;
+       IMG_UINT32 ui32BufferArrayLength;
+       IMG_BOOL bDumpPolls;
+} PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_UINT32 ui32DumpFrameNum;
+       IMG_BOOL bLastFrame;
+       IMG_UINT32 *pui32Registers;
+       IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMPCOUNTER_REGISTERS_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_UINT32 ui32DumpFrameNum;
+       IMG_BOOL bLastFrame;
+       IMG_UINT32 *pui32Registers;
+       IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_UINT32 ui32DumpFrameNum;
+       IMG_UINT32 ui32TAKickCount;
+       IMG_BOOL bLastFrame;
+       IMG_UINT32 *pui32Registers;
+       IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB_TAG
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_CHAR                        szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+       IMG_UINT32                      ui32FileOffset;
+       IMG_UINT32                      ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM
+{
+       IMG_UINT32                      ui32BridgeFlags; 
+       IMG_HANDLE                      hDevCookie;
+       IMG_CHAR                        szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+       IMG_UINT32                      ui32FileOffset;
+       IMG_DEV_VIRTADDR        sDevVAddr;
+       IMG_UINT32                      ui32Size;
+       IMG_UINT32                      ui32DataMaster;
+       IMG_UINT32                      ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM;
+
+#endif
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hHWRenderContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_HANDLE hHWRenderContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hHWTransferContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_HANDLE hHWTransferContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT_TAG
+{
+       IMG_UINT32 ui32BridgeFlags; 
+       IMG_HANDLE hDevCookie;
+       IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT;
+
+#define        SGX2D_MAX_BLT_CMD_SIZ           256     
+#endif 
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB_TAG
+{
+       IMG_UINT32                                      ui32BridgeFlags; 
+       IMG_HANDLE                                      hDevCookie;
+       IMG_UINT32                                      ui32ArraySize;
+       PVRSRV_SGX_HWPERF_CB_ENTRY      *psHWPerfCBData;
+} PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB_TAG
+{
+       PVRSRV_ERROR            eError;
+       IMG_UINT32                      ui32DataCount;
+       IMG_UINT32                      ui32ClockSpeed;
+       IMG_UINT32                      ui32HostTimeStamp;
+} PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/include/sgx_mkif_km.h b/drivers/staging/mrst/pvr/services4/include/sgx_mkif_km.h
new file mode 100644 (file)
index 0000000..6d72a18
--- /dev/null
@@ -0,0 +1,344 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined (__SGX_MKIF_KM_H__)
+#define __SGX_MKIF_KM_H__
+
+#include "img_types.h"
+#include "servicesint.h"
+#include "sgxapi_km.h"
+
+
+#if defined(SGX_FEATURE_MP)
+       #define SGX_REG_BANK_SHIFT                      (12)
+       #define SGX_REG_BANK_SIZE                       (0x4000)
+       #if defined(SGX541)
+               #define SGX_REG_BANK_BASE_INDEX         (1)
+               #define SGX_REG_BANK_MASTER_INDEX       (SGX_REG_BANK_BASE_INDEX + SGX_FEATURE_MP_CORE_COUNT)
+       #else
+               #define SGX_REG_BANK_BASE_INDEX         (2)
+               #define SGX_REG_BANK_MASTER_INDEX       (1)
+       #endif 
+       #define SGX_MP_CORE_SELECT(x,i)         (x + ((i + SGX_REG_BANK_BASE_INDEX) * SGX_REG_BANK_SIZE))
+       #define SGX_MP_MASTER_SELECT(x)         (x + (SGX_REG_BANK_MASTER_INDEX * SGX_REG_BANK_SIZE))
+#else
+       #define SGX_MP_CORE_SELECT(x,i)         (x)
+#endif 
+
+
+typedef struct _SGXMKIF_COMMAND_
+{
+       IMG_UINT32                              ui32ServiceAddress;             
+       IMG_UINT32                              ui32CacheControl;               
+       IMG_UINT32                              ui32Data[4];                    
+       IMG_UINT32                              ui32Padding[2];                 
+} SGXMKIF_COMMAND;
+
+
+typedef struct _PVRSRV_SGX_KERNEL_CCB_
+{
+       SGXMKIF_COMMAND         asCommands[256];                
+} PVRSRV_SGX_KERNEL_CCB;
+
+
+typedef struct _PVRSRV_SGX_CCB_CTL_
+{
+       IMG_UINT32                              ui32WriteOffset;                
+       IMG_UINT32                              ui32ReadOffset;                 
+} PVRSRV_SGX_CCB_CTL;
+
+
+typedef struct _SGXMKIF_HOST_CTL_
+{
+#if defined(PVRSRV_USSE_EDM_BREAKPOINTS)
+       IMG_UINT32                              ui32BreakpointDisable;
+       IMG_UINT32                              ui32Continue;
+#endif
+
+       volatile IMG_UINT32             ui32InitStatus;                         
+       volatile IMG_UINT32             ui32PowerStatus;                        
+       volatile IMG_UINT32             ui32CleanupStatus;                      
+#if defined(FIX_HW_BRN_28889)
+       volatile IMG_UINT32             ui32InvalStatus;                        
+#endif
+#if defined(SUPPORT_HW_RECOVERY)
+       IMG_UINT32                              ui32uKernelDetectedLockups;     
+       IMG_UINT32                              ui32HostDetectedLockups;        
+       IMG_UINT32                              ui32HWRecoverySampleRate;       
+#endif 
+       IMG_UINT32                              ui32uKernelTimerClock;          
+       IMG_UINT32                              ui32ActivePowManSampleRate;     
+       IMG_UINT32                              ui32InterruptFlags;             
+       IMG_UINT32                              ui32InterruptClearFlags;        
+       IMG_UINT32                              ui32BPSetClearSignal;           
+
+       IMG_UINT32                              ui32NumActivePowerEvents;       
+
+       IMG_UINT32                              ui32TimeWraps;                          
+       IMG_UINT32                              ui32HostClock;                          
+
+#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+       IMG_UINT32                              aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS]; 
+       IMG_UINT32                              aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];   
+#else
+       IMG_UINT32                              ui32PerfGroup;                                                                  
+#endif 
+} SGXMKIF_HOST_CTL;
+
+#define        SGXMKIF_CMDTA_CTRLFLAGS_READY                   0x00000001
+typedef struct _SGXMKIF_CMDTA_SHARED_
+{
+       IMG_UINT32                      ui32CtrlFlags;
+       
+       IMG_UINT32                      ui32NumTAStatusVals;
+       IMG_UINT32                      ui32Num3DStatusVals;
+
+       
+       IMG_UINT32                      ui32TATQSyncWriteOpsPendingVal;
+       IMG_DEV_VIRTADDR        sTATQSyncWriteOpsCompleteDevVAddr;
+       IMG_UINT32                      ui32TATQSyncReadOpsPendingVal;
+       IMG_DEV_VIRTADDR        sTATQSyncReadOpsCompleteDevVAddr;
+
+       
+       IMG_UINT32                      ui323DTQSyncWriteOpsPendingVal;
+       IMG_DEV_VIRTADDR        s3DTQSyncWriteOpsCompleteDevVAddr;
+       IMG_UINT32                      ui323DTQSyncReadOpsPendingVal;
+       IMG_DEV_VIRTADDR        s3DTQSyncReadOpsCompleteDevVAddr;
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+       
+       IMG_UINT32                                      ui32NumTASrcSyncs;
+       PVRSRV_DEVICE_SYNC_OBJECT       asTASrcSyncs[SGX_MAX_TA_SRC_SYNCS];
+       IMG_UINT32                                      ui32NumTADstSyncs;
+       PVRSRV_DEVICE_SYNC_OBJECT       asTADstSyncs[SGX_MAX_TA_DST_SYNCS];
+       IMG_UINT32                                      ui32Num3DSrcSyncs;
+       PVRSRV_DEVICE_SYNC_OBJECT       as3DSrcSyncs[SGX_MAX_3D_SRC_SYNCS];
+#else
+       
+       IMG_UINT32                      ui32NumSrcSyncs;
+       PVRSRV_DEVICE_SYNC_OBJECT       asSrcSyncs[SGX_MAX_SRC_SYNCS];
+#endif
+
+       
+       PVRSRV_DEVICE_SYNC_OBJECT       sTA3DDependency;
+
+       CTL_STATUS                      sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+       CTL_STATUS                      sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
+
+} SGXMKIF_CMDTA_SHARED;
+
+#define SGXTQ_MAX_STATUS                                               SGX_MAX_TRANSFER_STATUS_VALS + 2
+
+#define SGXMKIF_TQFLAGS_NOSYNCUPDATE                   0x00000001
+#define SGXMKIF_TQFLAGS_KEEPPENDING                            0x00000002
+#define SGXMKIF_TQFLAGS_TATQ_SYNC                              0x00000004
+#define SGXMKIF_TQFLAGS_3DTQ_SYNC                              0x00000008
+#if defined(SGX_FEATURE_FAST_RENDER_CONTEXT_SWITCH)
+#define SGXMKIF_TQFLAGS_CTXSWITCH                              0x00000010
+#endif
+#define SGXMKIF_TQFLAGS_DUMMYTRANSFER                  0x00000020
+
+typedef struct _SGXMKIF_TRANSFERCMD_SHARED_
+{
+       
+       
+       IMG_UINT32                      ui32NumSrcSyncs;
+       PVRSRV_DEVICE_SYNC_OBJECT       asSrcSyncs[SGX_MAX_SRC_SYNCS];
+       
+
+       IMG_UINT32                      ui32NumDstSyncs;
+       PVRSRV_DEVICE_SYNC_OBJECT       asDstSyncs[SGX_MAX_DST_SYNCS];
+       
+       IMG_UINT32              ui32DstReadOpPendingVal;
+       IMG_DEV_VIRTADDR        sDstReadOpsCompleteDevAddr;
+       
+       IMG_UINT32              ui32DstWriteOpPendingVal;
+       IMG_DEV_VIRTADDR        sDstWriteOpsCompleteDevAddr;
+
+       
+       IMG_UINT32              ui32TASyncWriteOpsPendingVal;
+       IMG_DEV_VIRTADDR        sTASyncWriteOpsCompleteDevVAddr;
+       IMG_UINT32              ui32TASyncReadOpsPendingVal;
+       IMG_DEV_VIRTADDR        sTASyncReadOpsCompleteDevVAddr;
+
+       
+       IMG_UINT32              ui323DSyncWriteOpsPendingVal;
+       IMG_DEV_VIRTADDR        s3DSyncWriteOpsCompleteDevVAddr;
+       IMG_UINT32              ui323DSyncReadOpsPendingVal;
+       IMG_DEV_VIRTADDR        s3DSyncReadOpsCompleteDevVAddr;
+
+       IMG_UINT32              ui32NumStatusVals;
+       CTL_STATUS      sCtlStatusInfo[SGXTQ_MAX_STATUS];
+} SGXMKIF_TRANSFERCMD_SHARED, *PSGXMKIF_TRANSFERCMD_SHARED;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGXMKIF_2DCMD_SHARED_ {
+       
+       IMG_UINT32                      ui32NumSrcSync;
+       PVRSRV_DEVICE_SYNC_OBJECT       sSrcSyncData[SGX_MAX_2D_SRC_SYNC_OPS];
+
+       
+       PVRSRV_DEVICE_SYNC_OBJECT       sDstSyncData;
+
+       
+       PVRSRV_DEVICE_SYNC_OBJECT       sTASyncData;
+
+       
+       PVRSRV_DEVICE_SYNC_OBJECT       s3DSyncData;
+} SGXMKIF_2DCMD_SHARED, *PSGXMKIF_2DCMD_SHARED;
+#endif 
+
+
+typedef struct _SGXMKIF_HWDEVICE_SYNC_LIST_
+{
+       IMG_DEV_VIRTADDR        sAccessDevAddr;
+       IMG_UINT32                      ui32NumSyncObjects;
+       
+       PVRSRV_DEVICE_SYNC_OBJECT       asSyncData[1];
+} SGXMKIF_HWDEVICE_SYNC_LIST, *PSGXMKIF_HWDEVICE_SYNC_LIST;
+
+
+#define PVRSRV_USSE_EDM_INIT_COMPLETE                  (1UL << 0)      
+
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE                           (1UL << 2)      
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE                       (1UL << 3)      
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE      (1UL << 4)      
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK                                         (1UL << 5)      
+
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR                  (1UL << 0)      
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1)      
+
+#define PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE    (1UL << 0)      
+
+#if defined(FIX_HW_BRN_28889)
+#define PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE             (1UL << 0)      
+#endif
+
+#define PVRSRV_USSE_MISCINFO_READY             0x1UL
+#define PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES  0x2UL   
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+#define PVRSRV_USSE_MISCINFO_MEMREAD                   0x4UL   
+#define PVRSRV_USSE_MISCINFO_MEMWRITE                  0x8UL   
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define PVRSRV_USSE_MISCINFO_MEMREAD_FAIL              0x1UL << 31     
+#endif
+#endif
+
+
+#define        PVRSRV_CLEANUPCMD_RT            0x1
+#define        PVRSRV_CLEANUPCMD_RC            0x2
+#define        PVRSRV_CLEANUPCMD_TC            0x3
+#define        PVRSRV_CLEANUPCMD_2DC           0x4
+#define        PVRSRV_CLEANUPCMD_PB            0x5
+
+#define PVRSRV_POWERCMD_POWEROFF       0x1
+#define PVRSRV_POWERCMD_IDLE           0x2
+#define PVRSRV_POWERCMD_RESUME         0x3
+
+
+#if defined(SGX_FEATURE_BIF_NUM_DIRLISTS)
+#define SGX_BIF_DIR_LIST_INDEX_EDM     (SGX_FEATURE_BIF_NUM_DIRLISTS - 1)
+#else
+#define SGX_BIF_DIR_LIST_INDEX_EDM     (0)
+#endif
+
+#define        SGXMKIF_CC_INVAL_BIF_PT 0x1
+#define        SGXMKIF_CC_INVAL_BIF_PD 0x2
+#define SGXMKIF_CC_INVAL_BIF_SL        0x4
+#define SGXMKIF_CC_INVAL_DATA  0x8
+
+
+typedef struct _SGX_MISCINFO_STRUCT_SIZES_
+{
+#if defined (SGX_FEATURE_2D_HARDWARE)
+       IMG_UINT32      ui32Sizeof_2DCMD;
+       IMG_UINT32      ui32Sizeof_2DCMD_SHARED;
+#endif
+       IMG_UINT32      ui32Sizeof_CMDTA;
+       IMG_UINT32      ui32Sizeof_CMDTA_SHARED;
+       IMG_UINT32      ui32Sizeof_TRANSFERCMD;
+       IMG_UINT32      ui32Sizeof_TRANSFERCMD_SHARED;
+       IMG_UINT32      ui32Sizeof_3DREGISTERS;
+       IMG_UINT32      ui32Sizeof_HWPBDESC;
+       IMG_UINT32      ui32Sizeof_HWRENDERCONTEXT;
+       IMG_UINT32      ui32Sizeof_HWRENDERDETAILS;
+       IMG_UINT32      ui32Sizeof_HWRTDATA;
+       IMG_UINT32      ui32Sizeof_HWRTDATASET;
+       IMG_UINT32      ui32Sizeof_HWTRANSFERCONTEXT;
+       IMG_UINT32      ui32Sizeof_HOST_CTL;
+       IMG_UINT32      ui32Sizeof_COMMAND;
+} SGX_MISCINFO_STRUCT_SIZES;
+
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+typedef struct _PVRSRV_SGX_MISCINFO_MEMACCESS
+{
+       IMG_DEV_VIRTADDR        sDevVAddr;              
+       IMG_DEV_PHYADDR         sPDDevPAddr;    
+} PVRSRV_SGX_MISCINFO_MEMACCESS;
+#endif
+
+typedef struct _PVRSRV_SGX_MISCINFO_INFO
+{
+       IMG_UINT32                                              ui32MiscInfoFlags;
+       PVRSRV_SGX_MISCINFO_FEATURES    sSGXFeatures;           
+       SGX_MISCINFO_STRUCT_SIZES               sSGXStructSizes;        
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+       PVRSRV_SGX_MISCINFO_MEMACCESS   sSGXMemAccessSrc;       
+       PVRSRV_SGX_MISCINFO_MEMACCESS   sSGXMemAccessDest;      
+#endif
+} PVRSRV_SGX_MISCINFO_INFO;
+
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+#define SGXMK_TRACE_BUFFER_SIZE 512
+#endif 
+
+#define SGXMKIF_HWPERF_CB_SIZE                                 0x100   
+
+typedef struct _SGXMKIF_HWPERF_CB_ENTRY_
+{
+       IMG_UINT32      ui32FrameNo;
+       IMG_UINT32      ui32Type;
+       IMG_UINT32      ui32Ordinal;
+       IMG_UINT32      ui32Info;
+       IMG_UINT32      ui32TimeWraps;
+       IMG_UINT32      ui32Time;
+       IMG_UINT32      ui32Counters[SGX_FEATURE_MP_CORE_COUNT][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+} SGXMKIF_HWPERF_CB_ENTRY;
+
+typedef struct _SGXMKIF_HWPERF_CB_
+{
+       IMG_UINT32                              ui32Woff;
+       IMG_UINT32                              ui32Roff;
+       IMG_UINT32                              ui32Ordinal;
+       SGXMKIF_HWPERF_CB_ENTRY psHWPerfCBData[SGXMKIF_HWPERF_CB_SIZE];
+} SGXMKIF_HWPERF_CB;
+
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/include/sgxinfo.h b/drivers/staging/mrst/pvr/services4/include/sgxinfo.h
new file mode 100644 (file)
index 0000000..50f1113
--- /dev/null
@@ -0,0 +1,287 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined (__SGXINFO_H__)
+#define __SGXINFO_H__
+
+#include "sgxscript.h"
+#include "servicesint.h"
+#include "services.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+
+
+#define SGX_MAX_DEV_DATA                       24
+#define        SGX_MAX_INIT_MEM_HANDLES        16
+
+
+typedef struct _SGX_BRIDGE_INFO_FOR_SRVINIT
+{
+       IMG_DEV_PHYADDR sPDDevPAddr;
+       PVRSRV_HEAP_INFO asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+} SGX_BRIDGE_INFO_FOR_SRVINIT;
+
+
+typedef enum _SGXMKIF_CMD_TYPE_
+{
+       SGXMKIF_CMD_TA                          = 0,
+       SGXMKIF_CMD_TRANSFER            = 1,
+       SGXMKIF_CMD_2D                          = 2,
+       SGXMKIF_CMD_POWER                       = 3,
+       SGXMKIF_CMD_CLEANUP                     = 4,
+       SGXMKIF_CMD_GETMISCINFO         = 5,
+       SGXMKIF_CMD_PROCESS_QUEUES      = 6,
+       SGXMKIF_CMD_DATABREAKPOINT      = 7,
+       SGXMKIF_CMD_SETHWPERFSTATUS     = 8,
+       SGXMKIF_CMD_MAX                         = 9,
+
+       SGXMKIF_CMD_FORCE_I32           = -1,
+
+} SGXMKIF_CMD_TYPE;
+
+
+typedef struct _SGX_BRIDGE_INIT_INFO_
+{
+       IMG_HANDLE      hKernelCCBMemInfo;
+       IMG_HANDLE      hKernelCCBCtlMemInfo;
+       IMG_HANDLE      hKernelCCBEventKickerMemInfo;
+       IMG_HANDLE      hKernelSGXHostCtlMemInfo;
+       IMG_HANDLE      hKernelSGXTA3DCtlMemInfo;
+       IMG_HANDLE      hKernelSGXMiscMemInfo;
+
+       IMG_UINT32      aui32HostKickAddr[SGXMKIF_CMD_MAX];
+
+       SGX_INIT_SCRIPTS sScripts;
+
+       IMG_UINT32      ui32ClientBuildOptions;
+       SGX_MISCINFO_STRUCT_SIZES       sSGXStructSizes;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+       IMG_HANDLE      hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+       IMG_HANDLE      hKernelHWPerfCBMemInfo;
+#endif
+       IMG_HANDLE      hKernelTASigBufferMemInfo;
+       IMG_HANDLE      hKernel3DSigBufferMemInfo;
+
+#if defined(FIX_HW_BRN_29702)
+       IMG_HANDLE      hKernelCFIMemInfo;
+#endif
+#if defined(FIX_HW_BRN_29823)
+       IMG_HANDLE      hKernelDummyTermStreamMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+       IMG_HANDLE      hKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+       IMG_HANDLE hKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+       IMG_HANDLE hKernelTmpDPMStateMemInfo;
+#endif
+
+       IMG_UINT32 ui32EDMTaskReg0;
+       IMG_UINT32 ui32EDMTaskReg1;
+
+       IMG_UINT32 ui32ClkGateStatusReg;
+       IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+       IMG_UINT32 ui32MasterClkGateStatusReg;
+       IMG_UINT32 ui32MasterClkGateStatusMask;
+       IMG_UINT32 ui32MasterClkGateStatus2Reg;
+       IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif 
+
+       IMG_UINT32 ui32CacheControl;
+
+       IMG_UINT32      asInitDevData[SGX_MAX_DEV_DATA];
+       IMG_HANDLE      asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+} SGX_BRIDGE_INIT_INFO;
+
+
+typedef struct _SGX_DEVICE_SYNC_LIST_
+{
+       PSGXMKIF_HWDEVICE_SYNC_LIST     psHWDeviceSyncList;
+
+       IMG_HANDLE                              hKernelHWSyncListMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  *psHWDeviceSyncListClientMemInfo;
+       PVRSRV_CLIENT_MEM_INFO  *psAccessResourceClientMemInfo;
+
+       volatile IMG_UINT32             *pui32Lock;
+
+       struct _SGX_DEVICE_SYNC_LIST_   *psNext;
+
+       
+       IMG_UINT32                      ui32NumSyncObjects;
+       IMG_HANDLE                      ahSyncHandles[1];
+} SGX_DEVICE_SYNC_LIST, *PSGX_DEVICE_SYNC_LIST;
+
+
+typedef struct _SGX_INTERNEL_STATUS_UPDATE_
+{
+       CTL_STATUS                              sCtlStatus;
+       IMG_HANDLE                              hKernelMemInfo;
+} SGX_INTERNEL_STATUS_UPDATE;
+
+
+typedef struct _SGX_CCB_KICK_
+{
+       SGXMKIF_COMMAND         sCommand;
+       IMG_HANDLE                      hCCBKernelMemInfo;
+
+       IMG_UINT32      ui32NumDstSyncObjects;
+       IMG_HANDLE      hKernelHWSyncListMemInfo;
+
+       
+       IMG_HANDLE      *pahDstSyncHandles;
+
+       IMG_UINT32      ui32NumTAStatusVals;
+       IMG_UINT32      ui32Num3DStatusVals;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+       SGX_INTERNEL_STATUS_UPDATE      asTAStatusUpdate[SGX_MAX_TA_STATUS_VALS];
+       SGX_INTERNEL_STATUS_UPDATE      as3DStatusUpdate[SGX_MAX_3D_STATUS_VALS];
+#else
+       IMG_HANDLE      ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+       IMG_HANDLE      ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#endif
+
+       IMG_BOOL        bFirstKickOrResume;
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+       IMG_BOOL        bTerminateOrAbort;
+#endif
+       IMG_BOOL        bLastInScene;
+
+       
+       IMG_UINT32      ui32CCBOffset;
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+       
+       IMG_UINT32      ui32NumTASrcSyncs;
+       IMG_HANDLE      ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
+       IMG_UINT32      ui32NumTADstSyncs;
+       IMG_HANDLE      ahTADstKernelSyncInfo[SGX_MAX_TA_DST_SYNCS];
+       IMG_UINT32      ui32Num3DSrcSyncs;
+       IMG_HANDLE      ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
+#else
+       
+       IMG_UINT32      ui32NumSrcSyncs;
+       IMG_HANDLE      ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+#endif
+
+       
+       IMG_BOOL        bTADependency;
+       IMG_HANDLE      hTA3DSyncInfo;
+
+       IMG_HANDLE      hTASyncInfo;
+       IMG_HANDLE      h3DSyncInfo;
+#if defined(PDUMP)
+       IMG_UINT32      ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+       IMG_UINT32      ui32WriteOpsPendingVal;
+#endif
+} SGX_CCB_KICK;
+
+
+#define SGX_KERNEL_USE_CODE_BASE_INDEX         15
+
+
+typedef struct _SGX_CLIENT_INFO_
+{
+       IMG_UINT32                                      ui32ProcessID;                  
+       IMG_VOID                                        *pvProcess;                             
+       PVRSRV_MISC_INFO                        sMiscInfo;                              
+
+       IMG_UINT32                                      asDevData[SGX_MAX_DEV_DATA];
+
+} SGX_CLIENT_INFO;
+
+typedef struct _SGX_INTERNAL_DEVINFO_
+{
+       IMG_UINT32                      ui32Flags;
+       IMG_HANDLE                      hHostCtlKernelMemInfoHandle;
+       IMG_BOOL                        bForcePTOff;
+} SGX_INTERNAL_DEVINFO;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct _PVRSRV_TRANSFER_SGX_KICK_
+{
+       IMG_HANDLE              hCCBMemInfo;
+       IMG_UINT32              ui32SharedCmdCCBOffset;
+
+       IMG_DEV_VIRTADDR        sHWTransferContextDevVAddr;
+
+       IMG_HANDLE              hTASyncInfo;
+       IMG_HANDLE              h3DSyncInfo;
+
+       IMG_UINT32              ui32NumSrcSync;
+       IMG_HANDLE              ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+       IMG_UINT32              ui32NumDstSync;
+       IMG_HANDLE              ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+       IMG_UINT32              ui32Flags;
+
+       IMG_UINT32              ui32PDumpFlags;
+#if defined(PDUMP)
+       IMG_UINT32              ui32CCBDumpWOff;
+#endif
+} PVRSRV_TRANSFER_SGX_KICK, *PPVRSRV_TRANSFER_SGX_KICK;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _PVRSRV_2D_SGX_KICK_
+{
+       IMG_HANDLE              hCCBMemInfo;
+       IMG_UINT32              ui32SharedCmdCCBOffset;
+
+       IMG_DEV_VIRTADDR        sHW2DContextDevVAddr;
+
+       IMG_UINT32              ui32NumSrcSync;
+       IMG_HANDLE              ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+       
+       IMG_HANDLE              hDstSyncInfo;
+
+       
+       IMG_HANDLE              hTASyncInfo;
+
+       
+       IMG_HANDLE              h3DSyncInfo;
+
+       IMG_UINT32              ui32PDumpFlags;
+#if defined(PDUMP)
+       IMG_UINT32              ui32CCBDumpWOff;
+#endif
+} PVRSRV_2D_SGX_KICK, *PPVRSRV_2D_SGX_KICK;
+#endif 
+#endif 
+
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/bridged/.gitignore b/drivers/staging/mrst/pvr/services4/srvkm/bridged/.gitignore
new file mode 100644 (file)
index 0000000..2f89523
--- /dev/null
@@ -0,0 +1,5 @@
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+*.o
+*.o.cmd
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c b/drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
new file mode 100644 (file)
index 0000000..66e4b23
--- /dev/null
@@ -0,0 +1,3964 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge_km.h"
+#include "pvr_debug.h"
+#include "ra.h"
+#include "pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "msvdx_bridge.h"
+#endif
+#include "perproc.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+#include "pdump_km.h"
+#include "syscommon.h"
+
+#include "bridged_pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "bridged_sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "bridged_vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "bridged_msvdx_bridge.h"
+#endif
+
+#include "env_data.h"
+
+#if defined (__linux__)
+#include "mmap.h"
+#endif
+
+#include "psb_intel_display.h" /* mdfld__intel_plane_set_alpha() */
+
+#include "srvkm.h"
+
+PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+#if defined(PVR_SECURE_HANDLES)
+static IMG_BOOL abSharedDeviceMemHeap[PVRSRV_MAX_CLIENT_HEAPS];
+static IMG_BOOL *pbSharedDeviceMemHeap = abSharedDeviceMemHeap;
+#else
+static IMG_BOOL *pbSharedDeviceMemHeap = (IMG_BOOL*)IMG_NULL;
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+                                       IMG_UINT32 ui32BridgeID,
+                                       IMG_VOID *pvDest,
+                                       IMG_VOID *pvSrc,
+                                       IMG_UINT32 ui32Size)
+{
+       g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes+=ui32Size;
+       g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+=ui32Size;
+       return OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+                                 IMG_UINT32 ui32BridgeID,
+                                 IMG_VOID *pvDest,
+                                 IMG_VOID *pvSrc,
+                                 IMG_UINT32 ui32Size)
+{
+       g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes+=ui32Size;
+       g_BridgeGlobalStats.ui32TotalCopyToUserBytes+=ui32Size;
+       return OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+
+static IMG_INT
+PVRSRVEnumerateDevicesBW(IMG_UINT32 ui32BridgeID,
+                                                IMG_VOID *psBridgeIn,
+                                                PVRSRV_BRIDGE_OUT_ENUMDEVICE *psEnumDeviceOUT,
+                                                PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DEVICES);
+
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+       psEnumDeviceOUT->eError =
+               PVRSRVEnumerateDevicesKM(&psEnumDeviceOUT->ui32NumDevices,
+                                                                psEnumDeviceOUT->asDeviceIdentifier);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVAcquireDeviceDataBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO *psAcquireDevInfoIN,
+                                                 PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO *psAcquireDevInfoOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO);
+
+       psAcquireDevInfoOUT->eError =
+               PVRSRVAcquireDeviceDataKM(psAcquireDevInfoIN->uiDevIndex,
+                                                                 psAcquireDevInfoIN->eDeviceType,
+                                                                 &hDevCookieInt);
+       if(psAcquireDevInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+               psAcquireDevInfoOUT->eError =
+               PVRSRVAllocHandle(psPerProc->psHandleBase,
+                                                 &psAcquireDevInfoOUT->hDevCookie,
+                                                 hDevCookieInt,
+                                                 PVRSRV_HANDLE_TYPE_DEV_NODE,
+                                                 PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+                                                          PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT *psCreateDevMemContextIN,
+                                                          PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT *psCreateDevMemContextOUT,
+                                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hDevMemContextInt;
+       IMG_UINT32 i;
+       IMG_BOOL bCreated;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
+
+       
+       NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS + 1);
+
+       psCreateDevMemContextOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psCreateDevMemContextIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psCreateDevMemContextOUT->eError =
+               PVRSRVCreateDeviceMemContextKM(hDevCookieInt,
+                                                                          psPerProc,
+                                                                          &hDevMemContextInt,
+                                                                          &psCreateDevMemContextOUT->ui32ClientHeapCount,
+                                                                          &psCreateDevMemContextOUT->sHeapInfo[0],
+                                                                          &bCreated,
+                                                                          pbSharedDeviceMemHeap);
+
+       if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       if(bCreated)
+       {
+               PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                                 &psCreateDevMemContextOUT->hDevMemContext,
+                                                 hDevMemContextInt,
+                                                 PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+                                                 PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+       }
+       else
+       {
+               psCreateDevMemContextOUT->eError =
+                       PVRSRVFindHandle(psPerProc->psHandleBase,
+                                                        &psCreateDevMemContextOUT->hDevMemContext,
+                                                        hDevMemContextInt,
+                                                        PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+               if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       for(i = 0; i < psCreateDevMemContextOUT->ui32ClientHeapCount; i++)
+       {
+               IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+               if(abSharedDeviceMemHeap[i])
+#endif
+               {
+                       
+                       PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+                                                         psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+                                                         PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+                                                         PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+               }
+#if defined(PVR_SECURE_HANDLES)
+               else
+               {
+                       
+                       if(bCreated)
+                       {
+                               PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+                                                                        psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+                                                                        PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+                                                                        PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                                                        psCreateDevMemContextOUT->hDevMemContext);
+                       }
+                       else
+                       {
+                               psCreateDevMemContextOUT->eError =
+                                       PVRSRVFindHandle(psPerProc->psHandleBase, &hDevMemHeapExt,
+                                                                        psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+                                                                        PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+                               if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+                               {
+                                       return 0;
+                               }
+                       }
+               }
+#endif
+               psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+       }
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+                                                               PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT *psDestroyDevMemContextIN,
+                                                               PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                               PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hDevMemContextInt;
+       IMG_BOOL bDestroyed;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psDestroyDevMemContextIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+                                                  psDestroyDevMemContextIN->hDevMemContext,
+                                                  PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVDestroyDeviceMemContextKM(hDevCookieInt, hDevMemContextInt, &bDestroyed);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       if(bDestroyed)
+       {
+               psRetOUT->eError =
+                       PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                               psDestroyDevMemContextIN->hDevMemContext,
+                                                               PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+       }
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
+                                                          PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoIN,
+                                                          PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoOUT,
+                                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hDevMemContextInt;
+       IMG_UINT32 i;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+       psGetDevMemHeapInfoOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psGetDevMemHeapInfoIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetDevMemHeapInfoOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+                                                  psGetDevMemHeapInfoIN->hDevMemContext,
+                                                  PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+       if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetDevMemHeapInfoOUT->eError =
+               PVRSRVGetDeviceMemHeapInfoKM(hDevCookieInt,
+                                                                          hDevMemContextInt,
+                                                                          &psGetDevMemHeapInfoOUT->ui32ClientHeapCount,
+                                                                          &psGetDevMemHeapInfoOUT->sHeapInfo[0],
+                                                                          pbSharedDeviceMemHeap);
+
+       if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       for(i = 0; i < psGetDevMemHeapInfoOUT->ui32ClientHeapCount; i++)
+       {
+               IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+               if(abSharedDeviceMemHeap[i])
+#endif
+               {
+                       
+                       PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+                                                         psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+                                                         PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+                                                         PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+               }
+#if defined(PVR_SECURE_HANDLES)
+               else
+               {
+                       
+                       psGetDevMemHeapInfoOUT->eError =
+                               PVRSRVFindHandle(psPerProc->psHandleBase, &hDevMemHeapExt,
+                                                                psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+                                                                PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+                       if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+                       {
+                               return 0;
+                       }
+               }
+#endif
+               psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+       }
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+                                          PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+                                          PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+                                          PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+                                          PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hDevMemHeapInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2);
+
+       psAllocDeviceMemOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psAllocDeviceMemIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psAllocDeviceMemOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemHeapInt,
+                                                  psAllocDeviceMemIN->hDevMemHeap,
+                                                  PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+
+       if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psAllocDeviceMemOUT->eError =
+               PVRSRVAllocDeviceMemKM(hDevCookieInt,
+                                                          psPerProc,
+                                                          hDevMemHeapInt,
+                                                          psAllocDeviceMemIN->ui32Attribs,
+                                                          psAllocDeviceMemIN->ui32Size,
+                                                          psAllocDeviceMemIN->ui32Alignment,
+                                                          &psMemInfo,
+                                                          "" );
+
+       if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       OSMemSet(&psAllocDeviceMemOUT->sClientMemInfo,
+                        0,
+                        sizeof(psAllocDeviceMemOUT->sClientMemInfo));
+
+       psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+                       psMemInfo->pvLinAddrKM;
+
+#if defined (__linux__)
+       psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = 0;
+#else
+       psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = psMemInfo->pvLinAddrKM;
+#endif
+       psAllocDeviceMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+       psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+       psAllocDeviceMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+       psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo,
+                                         psMemInfo,
+                                         PVRSRV_HANDLE_TYPE_MEM_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+       if(psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+       {
+               
+               OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo,
+                                0,
+                                sizeof (PVRSRV_CLIENT_SYNC_INFO));
+               psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+       }
+       else
+       {
+               
+
+               psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
+                       psMemInfo->psKernelSyncInfo->psSyncData;
+               psAllocDeviceMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+                       psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+               psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+                       psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+               psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo =
+                       psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+               PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                                        &psAllocDeviceMemOUT->sClientSyncInfo.hKernelSyncInfo,
+                                                        psMemInfo->psKernelSyncInfo,
+                                                        PVRSRV_HANDLE_TYPE_SYNC_INFO,
+                                                        PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                                        psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo);
+
+               psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
+                       &psAllocDeviceMemOUT->sClientSyncInfo;
+
+       }
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc);
+
+       return 0;
+}
+
+#endif 
+
+static IMG_INT
+PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_FREEDEVICEMEM *psFreeDeviceMemIN,
+                                         PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_VOID *pvKernelMemInfo;
+
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psFreeDeviceMemIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+                                                  psFreeDeviceMemIN->psKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = PVRSRVFreeDeviceMemKM(hDevCookieInt, pvKernelMemInfo);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psFreeDeviceMemIN->psKernelMemInfo,
+                                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM *psExportDeviceMemIN,
+                                         PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EXPORT_DEVICEMEM);
+
+       
+       psExportDeviceMemOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psExportDeviceMemIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find devcookie"));
+               return 0;
+       }
+
+       
+       psExportDeviceMemOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo,
+                                                  psExportDeviceMemIN->psKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+       if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find kernel meminfo"));
+               return 0;
+       }
+
+       
+       psExportDeviceMemOUT->eError =
+               PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+                                                        &psExportDeviceMemOUT->hMemInfo,
+                                                        psKernelMemInfo,
+                                                        PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psExportDeviceMemOUT->eError == PVRSRV_OK)
+       {
+               
+               PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVExportDeviceMemBW: allocation is already exported"));
+               return 0;
+       }
+
+       
+       psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+                                                                                                       &psExportDeviceMemOUT->hMemInfo,
+                                                                                                       psKernelMemInfo,
+                                                                                                       PVRSRV_HANDLE_TYPE_MEM_INFO,
+                                                                                                       PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+       if (psExportDeviceMemOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: failed to allocate handle from global handle list"));
+               return 0;
+       }
+
+       
+       psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+                                                        PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN,
+                                                        PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDevMemOUT,
+                                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_KERNEL_MEM_INFO  *psSrcKernelMemInfo = IMG_NULL;
+       PVRSRV_KERNEL_MEM_INFO  *psDstKernelMemInfo = IMG_NULL;
+       IMG_HANDLE                              hDstDevMemHeap = IMG_NULL;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEV_MEMORY);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2);
+
+       
+       psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+                                                                                               (IMG_VOID**)&psSrcKernelMemInfo,
+                                                                                               psMapDevMemIN->hKernelMemInfo,
+                                                                                               PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psMapDevMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                                               &hDstDevMemHeap,
+                                                                                               psMapDevMemIN->hDstDevMemHeap,
+                                                                                               PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+       if(psMapDevMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
+                                                                                                 psSrcKernelMemInfo,
+                                                                                                 hDstDevMemHeap,
+                                                                                                 &psDstKernelMemInfo);
+       if(psMapDevMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       OSMemSet(&psMapDevMemOUT->sDstClientMemInfo,
+                        0,
+                        sizeof(psMapDevMemOUT->sDstClientMemInfo));
+       OSMemSet(&psMapDevMemOUT->sDstClientSyncInfo,
+                        0,
+                        sizeof(psMapDevMemOUT->sDstClientSyncInfo));
+
+       psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+                       psDstKernelMemInfo->pvLinAddrKM;
+
+       psMapDevMemOUT->sDstClientMemInfo.pvLinAddr = 0;
+       psMapDevMemOUT->sDstClientMemInfo.sDevVAddr = psDstKernelMemInfo->sDevVAddr;
+       psMapDevMemOUT->sDstClientMemInfo.ui32Flags = psDstKernelMemInfo->ui32Flags;
+       psMapDevMemOUT->sDstClientMemInfo.ui32AllocSize = psDstKernelMemInfo->ui32AllocSize;
+       psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = psDstKernelMemInfo->sMemBlk.hOSMemHandle;
+
+       
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
+                                         psDstKernelMemInfo,
+                                         PVRSRV_HANDLE_TYPE_MEM_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+       psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+
+       
+       if(psDstKernelMemInfo->psKernelSyncInfo)
+       {
+               psMapDevMemOUT->sDstClientSyncInfo.psSyncData =
+                       psDstKernelMemInfo->psKernelSyncInfo->psSyncData;
+               psMapDevMemOUT->sDstClientSyncInfo.sWriteOpsCompleteDevVAddr =
+                       psDstKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+               psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
+                       psDstKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+               psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo =
+                       psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+               psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo = &psMapDevMemOUT->sDstClientSyncInfo;
+               
+               PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                         &psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo,
+                                         psDstKernelMemInfo->psKernelSyncInfo,
+                                         PVRSRV_HANDLE_TYPE_SYNC_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                         psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo);
+       }
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+                                                        PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY *psUnmapDevMemIN,
+                                                        PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo = IMG_NULL;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEV_MEMORY);
+
+       psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                                       (IMG_VOID**)&psKernelMemInfo,
+                                                                                       psUnmapDevMemIN->psKernelMemInfo,
+                                                                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psUnmapDevMemIN->psKernelMemInfo,
+                                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+       return 0;
+}
+
+
+
+static IMG_INT
+PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+                                                        PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *psMapDevClassMemIN,
+                                                        PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psMapDevClassMemOUT,
+                                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+       IMG_HANDLE hOSMapInfo;
+       IMG_HANDLE hDeviceClassBufferInt;
+       IMG_HANDLE hDevMemContextInt;
+       PVRSRV_HANDLE_TYPE eHandleType;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2);
+
+       
+       psMapDevClassMemOUT->eError =
+               PVRSRVLookupHandleAnyType(psPerProc->psHandleBase, &hDeviceClassBufferInt,
+                                                                 &eHandleType,
+                                                                 psMapDevClassMemIN->hDeviceClassBuffer);
+
+       if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       psMapDevClassMemOUT->eError =
+       PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+                                  psMapDevClassMemIN->hDevMemContext,
+                                  PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+       if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       switch(eHandleType)
+       {
+#if defined(PVR_SECURE_HANDLES)
+               case PVRSRV_HANDLE_TYPE_DISP_BUFFER:
+               case PVRSRV_HANDLE_TYPE_BUF_BUFFER:
+#else
+               case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+                       break;
+               default:
+                       psMapDevClassMemOUT->eError = PVRSRV_ERROR_INVALID_HANDLE_TYPE;
+                       return 0;
+       }
+
+       psMapDevClassMemOUT->eError =
+               PVRSRVMapDeviceClassMemoryKM(psPerProc,
+                                                                        hDevMemContextInt,
+                                                                        hDeviceClassBufferInt,
+                                                                        &psMemInfo,
+                                                                        &hOSMapInfo);
+       if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       OSMemSet(&psMapDevClassMemOUT->sClientMemInfo,
+                        0,
+                        sizeof(psMapDevClassMemOUT->sClientMemInfo));
+       OSMemSet(&psMapDevClassMemOUT->sClientSyncInfo,
+                        0,
+                        sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+       psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+                       psMemInfo->pvLinAddrKM;
+
+       psMapDevClassMemOUT->sClientMemInfo.pvLinAddr = 0;
+       psMapDevClassMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+       psMapDevClassMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+       psMapDevClassMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+       psMapDevClassMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                         &psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo,
+                                         psMemInfo,
+                                         PVRSRV_HANDLE_TYPE_MEM_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                         psMapDevClassMemIN->hDeviceClassBuffer);
+
+       psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+
+       
+       if(psMemInfo->psKernelSyncInfo)
+       {
+               psMapDevClassMemOUT->sClientSyncInfo.psSyncData =
+                       psMemInfo->psKernelSyncInfo->psSyncData;
+               psMapDevClassMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+                       psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+               psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+                       psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+               psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo =
+                       psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+               psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo = &psMapDevClassMemOUT->sClientSyncInfo;
+               
+               PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                                 &psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo,
+                                                 psMemInfo->psKernelSyncInfo,
+                                                 PVRSRV_HANDLE_TYPE_SYNC_INFO,
+                                                 PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                                 psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo);
+       }
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+                                                          PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY *psUnmapDevClassMemIN,
+                                                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvKernelMemInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+                                                  psUnmapDevClassMemIN->psKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = PVRSRVUnmapDeviceClassMemoryKM(pvKernelMemInfo);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psUnmapDevClassMemIN->psKernelMemInfo,
+                                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+       return 0;
+}
+
+
+#if defined(OS_PVRSRV_WRAP_EXT_MEM_BW)
+IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+                                         PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else 
+static IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+                                         PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hDevMemContextInt;
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+       IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+        IMG_UINT32 ui32PageTableSize = 0;
+       
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2);
+
+       
+       psWrapExtMemOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psWrapExtMemIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psWrapExtMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       psWrapExtMemOUT->eError =
+       PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+                                  psWrapExtMemIN->hDevMemContext,
+                                  PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+       if(psWrapExtMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       if(psWrapExtMemIN->ui32NumPageTableEntries)
+       {
+               ui32PageTableSize = psWrapExtMemIN->ui32NumPageTableEntries
+                                               * sizeof(IMG_SYS_PHYADDR);
+
+               ASSIGN_AND_EXIT_ON_ERROR(psWrapExtMemOUT->eError,
+                                 OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 ui32PageTableSize,
+                                 (IMG_VOID **)&psSysPAddr, 0,
+                                 "Page Table"));
+
+               if(CopyFromUserWrapper(psPerProc,
+                                                          ui32BridgeID,
+                                                          psSysPAddr,
+                                                          psWrapExtMemIN->psSysPAddr,
+                                                          ui32PageTableSize) != PVRSRV_OK)
+               {
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,      ui32PageTableSize, (IMG_VOID *)psSysPAddr, 0);
+                       
+                       return -EFAULT;
+               }
+       }
+               
+       psWrapExtMemOUT->eError =
+               PVRSRVWrapExtMemoryKM(hDevCookieInt,
+                                                         psPerProc,
+                                                         hDevMemContextInt,
+                                                         psWrapExtMemIN->ui32ByteSize,
+                                                         psWrapExtMemIN->ui32PageOffset,
+                                                         psWrapExtMemIN->bPhysContig,
+                                                         psSysPAddr,
+                                                         psWrapExtMemIN->pvLinAddr,
+                                                         psWrapExtMemIN->ui32Flags,
+                                                         &psMemInfo);
+
+       if(psWrapExtMemIN->ui32NumPageTableEntries)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         ui32PageTableSize,
+                         (IMG_VOID *)psSysPAddr, 0);
+               
+       }
+       
+       if(psWrapExtMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
+                       psMemInfo->pvLinAddrKM;
+
+       
+       psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
+       psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+       psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+       psWrapExtMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+       psWrapExtMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo,
+                                         psMemInfo,
+                                         PVRSRV_HANDLE_TYPE_MEM_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+       
+       psWrapExtMemOUT->sClientSyncInfo.psSyncData =
+               psMemInfo->psKernelSyncInfo->psSyncData;
+       psWrapExtMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+               psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+       psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+               psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+       psWrapExtMemOUT->sClientSyncInfo.hMappingInfo =
+               psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+       psWrapExtMemOUT->sClientMemInfo.psClientSyncInfo = &psWrapExtMemOUT->sClientSyncInfo;
+
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                         &psWrapExtMemOUT->sClientSyncInfo.hKernelSyncInfo,
+                                         (IMG_HANDLE)psMemInfo->psKernelSyncInfo,
+                                         PVRSRV_HANDLE_TYPE_SYNC_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                         psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc);
+
+       return 0;
+}
+#endif 
+
+static IMG_INT
+PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+                                               PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY *psUnwrapExtMemIN,
+                                               PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                               PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvMemInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvMemInfo,
+                                                  psUnwrapExtMemIN->hKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVUnwrapExtMemoryKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                  psUnwrapExtMemIN->hKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVGetFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+                                                PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
+                                                PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM *psGetFreeDeviceMemOUT,
+                                                PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETFREE_DEVICEMEM);
+
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psGetFreeDeviceMemOUT->eError =
+               PVRSRVGetFreeDeviceMemKM(psGetFreeDeviceMemIN->ui32Flags,
+                                                                &psGetFreeDeviceMemOUT->ui32Total,
+                                                                &psGetFreeDeviceMemOUT->ui32Free,
+                                                                &psGetFreeDeviceMemOUT->ui32LargestBlock);
+
+       return 0;
+}
+
+static IMG_INT
+PVRMMapOSMemHandleToMMapDataBW(IMG_UINT32 ui32BridgeID,
+                                                                 PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *psMMapDataIN,
+                                                                 PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *psMMapDataOUT,
+                                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
+
+#if defined (__linux__)
+       psMMapDataOUT->eError =
+               PVRMMapOSMemHandleToMMapData(psPerProc,
+                                                                               psMMapDataIN->hMHandle,
+                                                                               &psMMapDataOUT->ui32MMapOffset,
+                                                                               &psMMapDataOUT->ui32ByteOffset,
+                                                                               &psMMapDataOUT->ui32RealByteSize,
+                                                                               &psMMapDataOUT->ui32UserVAddr);
+#else  
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+       PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+       psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif 
+       return 0;
+}
+
+
+static IMG_INT
+PVRMMapReleaseMMapDataBW(IMG_UINT32 ui32BridgeID,
+                                                                 PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA *psMMapDataIN,
+                                                                 PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA *psMMapDataOUT,
+                                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
+
+#if defined (__linux__)
+       psMMapDataOUT->eError =
+               PVRMMapReleaseMMapData(psPerProc,
+                                                                               psMMapDataIN->hMHandle,
+                                                                               &psMMapDataOUT->bMUnmap,
+                                                                               &psMMapDataOUT->ui32RealByteSize,
+                                                                               &psMMapDataOUT->ui32UserVAddr);
+#else
+       
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+       PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+       psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif 
+       return 0;
+}
+
+
+#ifdef PDUMP
+static IMG_INT
+PDumpIsCaptureFrameBW(IMG_UINT32 ui32BridgeID,
+                                         IMG_VOID *psBridgeIn,
+                                         PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING *psPDumpIsCapturingOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_ISCAPTURING);
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psPDumpIsCapturingOUT->bIsCapturing = PDumpIsCaptureFrameKM();
+       psPDumpIsCapturingOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+static IMG_INT
+PDumpCommentBW(IMG_UINT32 ui32BridgeID,
+                          PVRSRV_BRIDGE_IN_PDUMP_COMMENT *psPDumpCommentIN,
+                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_COMMENT);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psRetOUT->eError = PDumpCommentKM(&psPDumpCommentIN->szComment[0],
+                                                                         psPDumpCommentIN->ui32Flags);
+       return 0;
+}
+
+static IMG_INT
+PDumpSetFrameBW(IMG_UINT32 ui32BridgeID,
+                               PVRSRV_BRIDGE_IN_PDUMP_SETFRAME *psPDumpSetFrameIN,
+                               PVRSRV_BRIDGE_RETURN *psRetOUT,
+                               PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SETFRAME);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psRetOUT->eError = PDumpSetFrameKM(psPDumpSetFrameIN->ui32Frame);
+
+       return 0;
+}
+
+static IMG_INT
+PDumpRegWithFlagsBW(IMG_UINT32 ui32BridgeID,
+                                       PVRSRV_BRIDGE_IN_PDUMP_DUMPREG *psPDumpRegDumpIN,
+                                       PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, 
+                                                  (IMG_VOID **)&psDeviceNode, 
+                                                  psPDumpRegDumpIN->hDevCookie, 
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = PDumpRegWithFlagsKM (psPDumpRegDumpIN->szRegRegion,
+                                                                                       psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+                                                                                       psPDumpRegDumpIN->sHWReg.ui32RegVal,
+                                                                                       psPDumpRegDumpIN->ui32Flags);
+
+       return 0;
+}
+
+static IMG_INT
+PDumpRegPolBW(IMG_UINT32 ui32BridgeID,
+                         PVRSRV_BRIDGE_IN_PDUMP_REGPOL *psPDumpRegPolIN,
+                         PVRSRV_BRIDGE_RETURN *psRetOUT,
+                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, 
+                                                  (IMG_VOID **)&psDeviceNode, 
+                                                  psPDumpRegPolIN->hDevCookie, 
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+
+       psRetOUT->eError = 
+               PDumpRegPolWithFlagsKM(psPDumpRegPolIN->szRegRegion,
+                                                          psPDumpRegPolIN->sHWReg.ui32RegAddr, 
+                                                          psPDumpRegPolIN->sHWReg.ui32RegVal,
+                                                          psPDumpRegPolIN->ui32Mask,
+                                                          psPDumpRegPolIN->ui32Flags);
+
+       return 0;
+}
+
+static IMG_INT
+PDumpMemPolBW(IMG_UINT32 ui32BridgeID,
+                         PVRSRV_BRIDGE_IN_PDUMP_MEMPOL *psPDumpMemPolIN,
+                         PVRSRV_BRIDGE_RETURN *psRetOUT,
+                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvMemInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPOL);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvMemInfo,
+                                                  psPDumpMemPolIN->psKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PDumpMemPolKM(((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo),
+                                         psPDumpMemPolIN->ui32Offset,
+                                         psPDumpMemPolIN->ui32Value,
+                                         psPDumpMemPolIN->ui32Mask,
+                                         psPDumpMemPolIN->eOperator,
+                                         psPDumpMemPolIN->ui32Flags,
+                                         MAKEUNIQUETAG(pvMemInfo));
+
+       return 0;
+}
+
+static IMG_INT
+PDumpMemBW(IMG_UINT32 ui32BridgeID,
+                  PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM *psPDumpMemDumpIN,
+                  PVRSRV_BRIDGE_RETURN *psRetOUT,
+                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvMemInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPMEM);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvMemInfo,
+                                                  psPDumpMemDumpIN->psKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PDumpMemUM(psPerProc,
+                                  psPDumpMemDumpIN->pvAltLinAddr,
+                                  psPDumpMemDumpIN->pvLinAddr,
+                                  pvMemInfo,
+                                  psPDumpMemDumpIN->ui32Offset,
+                                  psPDumpMemDumpIN->ui32Bytes,
+                                  psPDumpMemDumpIN->ui32Flags,
+                                  MAKEUNIQUETAG(pvMemInfo));
+
+       return 0;
+}
+
+static IMG_INT
+PDumpBitmapBW(IMG_UINT32 ui32BridgeID,
+                         PVRSRV_BRIDGE_IN_PDUMP_BITMAP *psPDumpBitmapIN,
+                         PVRSRV_BRIDGE_RETURN *psRetOUT,
+                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_HANDLE hDevMemContextInt;
+       
+       PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID **)&psDeviceNode,
+                                                  psPDumpBitmapIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(     psPerProc->psHandleBase,
+                                                       &hDevMemContextInt,
+                                                       psPDumpBitmapIN->hDevMemContext,
+                                                       PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+                                               
+       psRetOUT->eError =
+               PDumpBitmapKM(psDeviceNode,
+                                         &psPDumpBitmapIN->szFileName[0],
+                                         psPDumpBitmapIN->ui32FileOffset,
+                                         psPDumpBitmapIN->ui32Width,
+                                         psPDumpBitmapIN->ui32Height,
+                                         psPDumpBitmapIN->ui32StrideInBytes,
+                                         psPDumpBitmapIN->sDevBaseAddr,
+                                         hDevMemContextInt,
+                                         psPDumpBitmapIN->ui32Size,
+                                         psPDumpBitmapIN->ePixelFormat,
+                                         psPDumpBitmapIN->eMemFormat,
+                                         psPDumpBitmapIN->ui32Flags);
+
+       return 0;
+}
+
+static IMG_INT
+PDumpReadRegBW(IMG_UINT32 ui32BridgeID,
+                          PVRSRV_BRIDGE_IN_PDUMP_READREG *psPDumpReadRegIN,
+                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID **)&psDeviceNode,
+                                                  psPDumpReadRegIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       psRetOUT->eError =
+               PDumpReadRegKM(&psPDumpReadRegIN->szRegRegion[0],
+                                          &psPDumpReadRegIN->szFileName[0],
+                                          psPDumpReadRegIN->ui32FileOffset,
+                                          psPDumpReadRegIN->ui32Address,
+                                          psPDumpReadRegIN->ui32Size,
+                                          psPDumpReadRegIN->ui32Flags);
+
+       return 0;
+}
+
+static IMG_INT
+PDumpDriverInfoBW(IMG_UINT32 ui32BridgeID,
+                                 PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO *psPDumpDriverInfoIN,
+                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_UINT32 ui32PDumpFlags;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DRIVERINFO);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       ui32PDumpFlags = 0;
+       if(psPDumpDriverInfoIN->bContinuous)
+       {
+               ui32PDumpFlags |= PDUMP_FLAGS_CONTINUOUS;
+       }
+       psRetOUT->eError =
+               PDumpDriverInfoKM(&psPDumpDriverInfoIN->szString[0],
+                                                 ui32PDumpFlags);
+
+       return 0;
+}
+
+static IMG_INT
+PDumpSyncDumpBW(IMG_UINT32 ui32BridgeID,
+                               PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC *psPDumpSyncDumpIN,
+                               PVRSRV_BRIDGE_RETURN *psRetOUT,
+                               PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_UINT32 ui32Bytes = psPDumpSyncDumpIN->ui32Bytes;
+       IMG_VOID *pvSyncInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPSYNC);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+                                                  psPDumpSyncDumpIN->psKernelSyncInfo,
+                                                  PVRSRV_HANDLE_TYPE_SYNC_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PDumpMemUM(psPerProc,
+                                  psPDumpSyncDumpIN->pvAltLinAddr,
+                                  IMG_NULL,
+                                  ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+                                  psPDumpSyncDumpIN->ui32Offset,
+                                  ui32Bytes,
+                                  0,
+                                  MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+       return 0;
+}
+
+static IMG_INT
+PDumpSyncPolBW(IMG_UINT32 ui32BridgeID,
+                          PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL *psPDumpSyncPolIN,
+                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_UINT32 ui32Offset;
+       IMG_VOID *pvSyncInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SYNCPOL);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+                                                  psPDumpSyncPolIN->psKernelSyncInfo,
+                                                  PVRSRV_HANDLE_TYPE_SYNC_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       if(psPDumpSyncPolIN->bIsRead)
+       {
+               ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+       }
+       else
+       {
+               ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+       }
+
+       psRetOUT->eError =
+               PDumpMemPolKM(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+                                         ui32Offset,
+                                         psPDumpSyncPolIN->ui32Value,
+                                         psPDumpSyncPolIN->ui32Mask,
+                                         PDUMP_POLL_OPERATOR_EQUAL,
+                                         0,
+                                         MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+       return 0;
+}
+
+
+static IMG_INT
+PDumpCycleCountRegReadBW(IMG_UINT32 ui32BridgeID,
+                                                PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ *psPDumpCycleCountRegReadIN,
+                                                PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, 
+                                                  (IMG_VOID **)&psDeviceNode, 
+                                                  psPDumpCycleCountRegReadIN->hDevCookie, 
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       PDumpCycleCountRegRead(&psDeviceNode->sDevId,
+                                                  psPDumpCycleCountRegReadIN->ui32RegOffset,
+                                                  psPDumpCycleCountRegReadIN->bLastFrame);
+
+       psRetOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+static IMG_INT
+PDumpPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+                                 PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR *psPDumpPDDevPAddrIN,
+                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvMemInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &pvMemInfo,
+                                                  psPDumpPDDevPAddrIN->hKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PDumpPDDevPAddrKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo,
+                                                 psPDumpPDDevPAddrIN->ui32Offset,
+                                                 psPDumpPDDevPAddrIN->sPDDevPAddr,
+                                                 MAKEUNIQUETAG(pvMemInfo),
+                                                 PDUMP_PD_UNIQUETAG);
+       return 0;
+}
+
+static IMG_INT
+PDumpStartInitPhaseBW(IMG_UINT32 ui32BridgeID,
+                                         IMG_VOID *psBridgeIn,
+                                         PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STARTINITPHASE);
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psRetOUT->eError = PDumpStartInitPhaseKM();
+
+       return 0;
+}
+
+static IMG_INT
+PDumpStopInitPhaseBW(IMG_UINT32 ui32BridgeID,
+                                         IMG_VOID *psBridgeIn,
+                                         PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STOPINITPHASE);
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psRetOUT->eError = PDumpStopInitPhaseKM();
+
+       return 0;
+}
+
+#endif 
+
+
+static IMG_INT
+PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+                                       PVRSRV_BRIDGE_IN_GET_MISC_INFO *psGetMiscInfoIN,
+                                       PVRSRV_BRIDGE_OUT_GET_MISC_INFO *psGetMiscInfoOUT,
+                                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_ERROR eError;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
+       OSMemCopy(&psGetMiscInfoOUT->sMiscInfo,
+                 &psGetMiscInfoIN->sMiscInfo,
+                 sizeof(PVRSRV_MISC_INFO));
+
+       if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) &&
+           ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) &&
+           ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
+       {
+               
+               psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+
+       if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) ||
+           ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) ||
+           ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
+       {
+               
+               ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+                                   OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                   psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+                                   (IMG_VOID **)&psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0,
+                                                       "Output string buffer"));
+
+               psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+
+               
+               eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+                                          psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
+                                          psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
+                                          psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
+
+               
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+                        (IMG_VOID *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
+               psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = IMG_NULL;
+
+               
+               psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
+
+               if(eError != PVRSRV_OK)
+               {
+                       
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoBW Error copy to user"));
+                       return -EFAULT;
+               }
+       }
+       else
+       {
+               psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+       }
+
+       
+       if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       if (psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
+       {
+               psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+                                                                                                       &psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+                                                                                                       psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+                                                                                                       PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+                                                                                                       PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+                       if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+                       {
+                               return 0;
+                       }
+       }
+
+       if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle)
+       {
+               
+               psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+                                                 &psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+                                                 psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+                                                 PVRSRV_HANDLE_TYPE_SOC_TIMER,
+                                                 PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+               if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVConnectBW(IMG_UINT32 ui32BridgeID,
+                               PVRSRV_BRIDGE_IN_CONNECT_SERVICES *psConnectServicesIN,
+                               PVRSRV_BRIDGE_OUT_CONNECT_SERVICES *psConnectServicesOUT,
+                               PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+#if defined(PDUMP)
+       
+       psPerProc->bPDumpPersistent |= ( (psConnectServicesIN->ui32Flags & SRV_FLAGS_PERSIST) != 0) ? IMG_TRUE : IMG_FALSE;
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+       psPerProc->bPDumpActive |= ( (psConnectServicesIN->ui32Flags & SRV_FLAGS_PDUMP_ACTIVE) != 0) ? IMG_TRUE : IMG_FALSE;
+#endif
+#else
+       PVR_UNREFERENCED_PARAMETER(psConnectServicesIN);
+#endif
+       psConnectServicesOUT->hKernelServices = psPerProc->hPerProcData;
+       psConnectServicesOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVDisconnectBW(IMG_UINT32 ui32BridgeID,
+                                  IMG_VOID *psBridgeIn,
+                                  PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DISCONNECT_SERVICES);
+
+       
+       psRetOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVEnumerateDCBW(IMG_UINT32 ui32BridgeID,
+                                       PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
+                                       PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
+                                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_CLASS);
+
+       psEnumDispClassOUT->eError =
+               PVRSRVEnumerateDCKM(psEnumDispClassIN->sDeviceClass,
+                                                       &psEnumDispClassOUT->ui32NumDevices,
+                                                       &psEnumDispClassOUT->ui32DevID[0]);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVOpenDCDeviceBW(IMG_UINT32 ui32BridgeID,
+                                        PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceIN,
+                                        PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceOUT,
+                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hDispClassInfoInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc, 1);
+
+       psOpenDispClassDeviceOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psOpenDispClassDeviceIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psOpenDispClassDeviceOUT->eError =
+               PVRSRVOpenDCDeviceKM(psPerProc,
+                                                        psOpenDispClassDeviceIN->ui32DeviceID,
+                                                        hDevCookieInt,
+                                                        &hDispClassInfoInt);
+
+       if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psOpenDispClassDeviceOUT->hDeviceKM,
+                                         hDispClassInfoInt,
+                                         PVRSRV_HANDLE_TYPE_DISP_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+       COMMIT_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVCloseDCDeviceBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE *psCloseDispClassDeviceIN,
+                                         PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfoInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfoInt,
+                                                  psCloseDispClassDeviceIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt, IMG_FALSE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psCloseDispClassDeviceIN->hDeviceKM,
+                                                       PVRSRV_HANDLE_TYPE_DISP_INFO);
+       return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCFormatsBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsIN,
+                                         PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfoInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS);
+
+       psEnumDispClassFormatsOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfoInt,
+                                                  psEnumDispClassFormatsIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psEnumDispClassFormatsOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psEnumDispClassFormatsOUT->eError =
+               PVRSRVEnumDCFormatsKM(pvDispClassInfoInt,
+                                                         &psEnumDispClassFormatsOUT->ui32Count,
+                                                         psEnumDispClassFormatsOUT->asFormat);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCDimsBW(IMG_UINT32 ui32BridgeID,
+                                  PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsIN,
+                                  PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsOUT,
+                                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfoInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS);
+
+       psEnumDispClassDimsOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfoInt,
+                                                  psEnumDispClassDimsIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+       if(psEnumDispClassDimsOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psEnumDispClassDimsOUT->eError =
+               PVRSRVEnumDCDimsKM(pvDispClassInfoInt,
+                                                  &psEnumDispClassDimsIN->sFormat,
+                                                  &psEnumDispClassDimsOUT->ui32Count,
+                                                  psEnumDispClassDimsOUT->asDim);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,  
+                                                 PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hBufferInt;
+       IMG_VOID *pvDispClassInfoInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc, 1);
+
+       psGetDispClassSysBufferOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfoInt,
+                                                  psGetDispClassSysBufferIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetDispClassSysBufferOUT->eError =
+               PVRSRVGetDCSystemBufferKM(pvDispClassInfoInt,
+                                                                 &hBufferInt);
+
+       if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+        
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                                &psGetDispClassSysBufferOUT->hBuffer,
+                                                hBufferInt,
+                                                PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+                                                (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+                                                psGetDispClassSysBufferIN->hDeviceKM);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCInfoBW(IMG_UINT32 ui32BridgeID,
+                                 PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO *psGetDispClassInfoIN,
+                                 PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO *psGetDispClassInfoOUT,
+                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_INFO);
+
+       psGetDispClassInfoOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psGetDispClassInfoIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psGetDispClassInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetDispClassInfoOUT->eError =
+               PVRSRVGetDCInfoKM(pvDispClassInfo,
+                                                 &psGetDispClassInfoOUT->sDisplayInfo);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVCreateDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainIN,
+                                                 PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+       IMG_HANDLE hSwapChainInt;
+       IMG_UINT32      ui32SwapChainID;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc, 1);
+
+       psCreateDispClassSwapChainOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psCreateDispClassSwapChainIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+       if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
+
+       psCreateDispClassSwapChainOUT->eError =
+               PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+                                                                 psCreateDispClassSwapChainIN->ui32Flags,
+                                                                 &psCreateDispClassSwapChainIN->sDstSurfAttrib,
+                                                                 &psCreateDispClassSwapChainIN->sSrcSurfAttrib,
+                                                                 psCreateDispClassSwapChainIN->ui32BufferCount,
+                                                                 psCreateDispClassSwapChainIN->ui32OEMFlags,
+                                                                 &hSwapChainInt,
+                                                                 &ui32SwapChainID);
+
+       if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
+
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                         &psCreateDispClassSwapChainOUT->hSwapChain,
+                                         hSwapChainInt,
+                                         PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                         psCreateDispClassSwapChainIN->hDeviceKM);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+                                                  PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN *psDestroyDispClassSwapChainIN,
+                                                  PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvSwapChain;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSwapChain,
+                                                  psDestroyDispClassSwapChainIN->hSwapChain,
+                                                  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVDestroyDCSwapChainKM(pvSwapChain);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psDestroyDispClassSwapChainIN->hSwapChain,
+                                                       PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstRectBW(IMG_UINT32 ui32BridgeID,
+                                        PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassDstRectIN,
+                                        PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+       IMG_VOID *pvSwapChain;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psSetDispClassDstRectIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvSwapChain,
+                                                  psSetDispClassDstRectIN->hSwapChain,
+                                                  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVSetDCDstRectKM(pvDispClassInfo,
+                                                        pvSwapChain,
+                                                        &psSetDispClassDstRectIN->sRect);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcRectBW(IMG_UINT32 ui32BridgeID,
+                                        PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassSrcRectIN,
+                                        PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+       IMG_VOID *pvSwapChain;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psSetDispClassSrcRectIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvSwapChain,
+                                                  psSetDispClassSrcRectIN->hSwapChain,
+                                                  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVSetDCSrcRectKM(pvDispClassInfo,
+                                                        pvSwapChain,
+                                                        &psSetDispClassSrcRectIN->sRect);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstColourKeyBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+                                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+       IMG_VOID *pvSwapChain;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY);
+
+       /* XXX this is a workaround, will have a formal implementation later on */
+       if ((IMG_UINT32)psSetDispClassColKeyIN->hSwapChain == 0xC0C0C0C0) {
+               if ( (IMG_UINT32)psSetDispClassColKeyIN->ui32CKColour == 0xD0D0D0D0) {
+                       mdfld__intel_plane_set_alpha(IMG_TRUE);
+               } else if ((IMG_UINT32)psSetDispClassColKeyIN->ui32CKColour == 0xE0E0E0E0) {
+                       mdfld__intel_plane_set_alpha(IMG_FALSE);
+               }
+               psRetOUT->eError = PVRSRV_OK;
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psSetDispClassColKeyIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvSwapChain,
+                                                  psSetDispClassColKeyIN->hSwapChain,
+                                                  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVSetDCDstColourKeyKM(pvDispClassInfo,
+                                                                 pvSwapChain,
+                                                                 psSetDispClassColKeyIN->ui32CKColour);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcColourKeyBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+                                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+       IMG_VOID *pvSwapChain;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psSetDispClassColKeyIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvSwapChain,
+                                                  psSetDispClassColKeyIN->hSwapChain,
+                                                  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVSetDCSrcColourKeyKM(pvDispClassInfo,
+                                                                 pvSwapChain,
+                                                                 psSetDispClassColKeyIN->ui32CKColour);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCBuffersBW(IMG_UINT32 ui32BridgeID,
+                                        PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersIN,
+                                        PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersOUT,
+                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+       IMG_VOID *pvSwapChain;
+       IMG_UINT32 i;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc, PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+       psGetDispClassBuffersOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psGetDispClassBuffersIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetDispClassBuffersOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvSwapChain,
+                                                  psGetDispClassBuffersIN->hSwapChain,
+                                                  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+       if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetDispClassBuffersOUT->eError =
+               PVRSRVGetDCBuffersKM(pvDispClassInfo,
+                                                        pvSwapChain,
+                                                        &psGetDispClassBuffersOUT->ui32BufferCount,
+                                                        psGetDispClassBuffersOUT->ahBuffer);
+       if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       PVR_ASSERT(psGetDispClassBuffersOUT->ui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+       for(i = 0; i < psGetDispClassBuffersOUT->ui32BufferCount; i++)
+       {
+               IMG_HANDLE hBufferExt;
+
+                
+               PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                                        &hBufferExt,
+                                                        psGetDispClassBuffersOUT->ahBuffer[i],
+                                                        PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+                                                        (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+                                                        psGetDispClassBuffersIN->hSwapChain);
+
+               psGetDispClassBuffersOUT->ahBuffer[i] = hBufferExt;
+       }
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCBufferBW(IMG_UINT32 ui32BridgeID,
+                                          PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER *psSwapDispClassBufferIN,
+                                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+       IMG_VOID *pvSwapChainBuf;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psSwapDispClassBufferIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+                                                  &pvSwapChainBuf,
+                                                  psSwapDispClassBufferIN->hBuffer,
+                                                  PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+                                                  psSwapDispClassBufferIN->hDeviceKM);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVSwapToDCBufferKM(pvDispClassInfo,
+                                                          pvSwapChainBuf,
+                                                          psSwapDispClassBufferIN->ui32SwapInterval,
+                                                          psSwapDispClassBufferIN->hPrivateTag,
+                                                          psSwapDispClassBufferIN->ui32ClipRectCount,
+                                                          psSwapDispClassBufferIN->sClipRect,
+                                                          psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCSystemBW(IMG_UINT32 ui32BridgeID,
+                                          PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
+                                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvDispClassInfo;
+       IMG_VOID *pvSwapChain;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvDispClassInfo,
+                                                  psSwapDispClassSystemIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_DISP_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+                                                  &pvSwapChain,
+                                                  psSwapDispClassSystemIN->hSwapChain,
+                                                  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+                                                  psSwapDispClassSystemIN->hDeviceKM);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+       psRetOUT->eError =
+               PVRSRVSwapToDCSystemKM(pvDispClassInfo,
+                                                          pvSwapChain);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCFrontBufferBW(IMG_UINT32 ui32BridgeID,
+                                          PVRSRV_BRIDGE_IN_GET_DISPCLASS_FRONT_BUFFER *psSwapDispClassSystemIN,
+                                          PVRSRV_BRIDGE_OUT_GET_DISPCLASS_FRONT_BUFFER *psSwapDispClassSystemOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_FRONT_BUFFER);
+       psSwapDispClassSystemOUT->eError = PVRSRV_ERROR_GENERIC;
+       return 0;
+}
+
+static IMG_INT
+PVRSRVOpenBCDeviceBW(IMG_UINT32 ui32BridgeID,
+                                        PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceIN,
+                                        PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceOUT,
+                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hBufClassInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc, 1);
+
+       psOpenBufferClassDeviceOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psOpenBufferClassDeviceIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psOpenBufferClassDeviceOUT->eError =
+               PVRSRVOpenBCDeviceKM(psPerProc,
+                                                        psOpenBufferClassDeviceIN->ui32DeviceID,
+                                                        hDevCookieInt,
+                                                        &hBufClassInfo);
+       if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psOpenBufferClassDeviceOUT->hDeviceKM,
+                                         hBufClassInfo,
+                                         PVRSRV_HANDLE_TYPE_BUF_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVCloseBCDeviceBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE *psCloseBufferClassDeviceIN,
+                                         PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvBufClassInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvBufClassInfo,
+                                                  psCloseBufferClassDeviceIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_BUF_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVCloseBCDeviceKM(pvBufClassInfo, IMG_FALSE);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                                                  psCloseBufferClassDeviceIN->hDeviceKM,
+                                                                                  PVRSRV_HANDLE_TYPE_BUF_INFO);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCInfoBW(IMG_UINT32 ui32BridgeID,
+                                 PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO *psGetBufferClassInfoIN,
+                                 PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO *psGetBufferClassInfoOUT,
+                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvBufClassInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO);
+
+       psGetBufferClassInfoOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvBufClassInfo,
+                                                  psGetBufferClassInfoIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_BUF_INFO);
+       if(psGetBufferClassInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetBufferClassInfoOUT->eError =
+               PVRSRVGetBCInfoKM(pvBufClassInfo,
+                                                 &psGetBufferClassInfoOUT->sBufferInfo);
+       return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCBufferBW(IMG_UINT32 ui32BridgeID,
+                                       PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+                                       PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+                                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_VOID *pvBufClassInfo;
+       IMG_HANDLE hBufferInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc, 1);
+
+       psGetBufferClassBufferOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &pvBufClassInfo,
+                                                  psGetBufferClassBufferIN->hDeviceKM,
+                                                  PVRSRV_HANDLE_TYPE_BUF_INFO);
+       if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetBufferClassBufferOUT->eError =
+               PVRSRVGetBCBufferKM(pvBufClassInfo,
+                                                       psGetBufferClassBufferIN->ui32BufferIndex,
+                                                       &hBufferInt);
+
+       if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+        
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                                &psGetBufferClassBufferOUT->hBuffer,
+                                                hBufferInt,
+                                                PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+                                                (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE |  PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+                                                psGetBufferClassBufferIN->hDeviceKM);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVAllocSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+                                                        PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemIN,
+                                                        PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemOUT,
+                                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc, 1);
+
+       psAllocSharedSysMemOUT->eError =
+               PVRSRVAllocSharedSysMemoryKM(psPerProc,
+                                                                        psAllocSharedSysMemIN->ui32Flags,
+                                                                        psAllocSharedSysMemIN->ui32Size,
+                                                                        &psKernelMemInfo);
+       if(psAllocSharedSysMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       OSMemSet(&psAllocSharedSysMemOUT->sClientMemInfo,
+                        0,
+                        sizeof(psAllocSharedSysMemOUT->sClientMemInfo));
+
+       psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+                       psKernelMemInfo->pvLinAddrKM;
+
+       psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddr = 0;
+       psAllocSharedSysMemOUT->sClientMemInfo.ui32Flags =
+               psKernelMemInfo->ui32Flags;
+       psAllocSharedSysMemOUT->sClientMemInfo.ui32AllocSize =
+               psKernelMemInfo->ui32AllocSize;
+       psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psAllocSharedSysMemOUT->sClientMemInfo.hKernelMemInfo,
+                                         psKernelMemInfo,
+                                         PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVFreeSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+                                                       PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM *psFreeSharedSysMemIN,
+                                                       PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM *psFreeSharedSysMemOUT,
+                                                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM);
+
+       psFreeSharedSysMemOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  (IMG_VOID **)&psKernelMemInfo,
+                                                  psFreeSharedSysMemIN->psKernelMemInfo,
+                                                                                                                                  PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+
+       if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+               return 0;
+
+       psFreeSharedSysMemOUT->eError =
+               PVRSRVFreeSharedSysMemoryKM(psKernelMemInfo);
+       if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+               return 0;
+
+       psFreeSharedSysMemOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psFreeSharedSysMemIN->psKernelMemInfo,
+                                                       PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+       return 0;
+}
+
+static IMG_INT
+PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM *psMapMemInfoMemIN,
+                                         PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM *psMapMemInfoMemOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+       PVRSRV_HANDLE_TYPE eHandleType;
+       IMG_HANDLE      hParent;
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_MEMINFO_MEM);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc, 2);
+
+       psMapMemInfoMemOUT->eError =
+               PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+                                                  (IMG_VOID **)&psKernelMemInfo,
+                                                  &eHandleType,
+                                                  psMapMemInfoMemIN->hKernelMemInfo);
+       if(psMapMemInfoMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       switch (eHandleType)
+       {
+#if defined(PVR_SECURE_HANDLES)
+               case PVRSRV_HANDLE_TYPE_MEM_INFO:
+               case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+               case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+#else
+               case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+                       break;
+               default:
+                       psMapMemInfoMemOUT->eError = PVRSRV_ERROR_INVALID_HANDLE_TYPE;
+                       return 0;
+       }
+
+       
+       psMapMemInfoMemOUT->eError =
+               PVRSRVGetParentHandle(psPerProc->psHandleBase,
+                                       &hParent,
+                                       psMapMemInfoMemIN->hKernelMemInfo,
+                                       eHandleType);
+       if (psMapMemInfoMemOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+       if (hParent == IMG_NULL)
+       {
+               hParent = psMapMemInfoMemIN->hKernelMemInfo;
+       }
+
+       OSMemSet(&psMapMemInfoMemOUT->sClientMemInfo,
+                        0,
+                        sizeof(psMapMemInfoMemOUT->sClientMemInfo));
+
+       psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+                       psKernelMemInfo->pvLinAddrKM;
+
+       psMapMemInfoMemOUT->sClientMemInfo.pvLinAddr = 0;
+       psMapMemInfoMemOUT->sClientMemInfo.sDevVAddr =
+               psKernelMemInfo->sDevVAddr;
+       psMapMemInfoMemOUT->sClientMemInfo.ui32Flags =
+               psKernelMemInfo->ui32Flags;
+       psMapMemInfoMemOUT->sClientMemInfo.ui32AllocSize =
+               psKernelMemInfo->ui32AllocSize;
+       psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                         &psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo,
+                                         psKernelMemInfo,
+                                         PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                         hParent);
+
+       if(psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+       {
+               
+               OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo,
+                                0,
+                                sizeof (PVRSRV_CLIENT_SYNC_INFO));
+       }
+       else
+       {
+               
+               psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
+                       psKernelMemInfo->psKernelSyncInfo->psSyncData;
+               psMapMemInfoMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+                       psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+               psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+                       psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+               psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo =
+                       psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+               psMapMemInfoMemOUT->sClientMemInfo.psClientSyncInfo = &psMapMemInfoMemOUT->sClientSyncInfo;
+
+               PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                                        &psMapMemInfoMemOUT->sClientSyncInfo.hKernelSyncInfo,
+                                                        psKernelMemInfo->psKernelSyncInfo,
+                                                        PVRSRV_HANDLE_TYPE_SYNC_INFO,
+                                                        PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                                        psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo);
+       }
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+
+static IMG_INT
+MMU_GetPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+                                       PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrIN,
+                                       PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrOUT,
+                                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevMemContextInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR);
+
+       psGetMmuPDDevPAddrOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+                                                  psGetMmuPDDevPAddrIN->hDevMemContext,
+                                                  PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+       if(psGetMmuPDDevPAddrOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetMmuPDDevPAddrOUT->sPDDevPAddr =
+               BM_GetDeviceNode(hDevMemContextInt)->pfnMMUGetPDDevPAddr(BM_GetMMUContextFromMemContext(hDevMemContextInt));
+       if(psGetMmuPDDevPAddrOUT->sPDDevPAddr.uiAddr)
+       {
+               psGetMmuPDDevPAddrOUT->eError = PVRSRV_OK;
+       }
+       else
+       {
+               psGetMmuPDDevPAddrOUT->eError = PVRSRV_ERROR_INVALID_PHYS_ADDR;
+       }
+       return 0;
+}
+
+
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+               IMG_VOID *psBridgeIn,
+               IMG_VOID *psBridgeOut,
+               PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if !defined(DEBUG)
+       PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+#endif
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+       PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+#if defined(DEBUG_BRIDGE_KM)
+       PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u (%s) mapped to "
+                        "Dummy Wrapper (probably not what you want!)",
+                        __FUNCTION__, ui32BridgeID, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#else
+       PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u mapped to "
+                        "Dummy Wrapper (probably not what you want!)",
+                        __FUNCTION__, ui32BridgeID));
+#endif
+       return -ENOTTY;
+}
+
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+                                          const IMG_CHAR *pszIOCName,
+                                          BridgeWrapperFunction pfFunction,
+                                          const IMG_CHAR *pszFunctionName,
+                                          size_t in_size, size_t out_size,
+                                          off_t err_offset)
+{
+       static IMG_UINT32 ui32PrevIndex = ~0UL;         
+#if !defined(DEBUG)
+       PVR_UNREFERENCED_PARAMETER(pszIOCName);
+#endif
+#if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
+       PVR_UNREFERENCED_PARAMETER(pszFunctionName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+       
+       PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
+#endif
+
+       
+       if(g_BridgeDispatchTable[ui32Index].pfFunction)
+       {
+#if defined(DEBUG_BRIDGE_KM)
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
+                                __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName));
+#else
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%u)",
+                                __FUNCTION__, pszIOCName, ui32Index));
+#endif
+               PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+       }
+
+       
+       if((ui32PrevIndex != ~0UL) &&
+          ((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
+               (ui32Index <= ui32PrevIndex)))
+       {
+#if defined(DEBUG_BRIDGE_KM)
+               PVR_DPF((PVR_DBG_WARNING,
+                                "%s: There is a gap in the dispatch table between indices %u (%s) and %u (%s)",
+                                __FUNCTION__, ui32PrevIndex, g_BridgeDispatchTable[ui32PrevIndex].pszIOCName,
+                                ui32Index, pszIOCName));
+#else
+               PVR_DPF((PVR_DBG_WARNING,
+                                "%s: There is a gap in the dispatch table between indices %u and %u (%s)",
+                                __FUNCTION__, (IMG_UINT)ui32PrevIndex, (IMG_UINT)ui32Index, pszIOCName));
+#endif
+               PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+       }
+
+       g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+       g_BridgeDispatchTable[ui32Index].in_size = in_size;
+       g_BridgeDispatchTable[ui32Index].out_size = out_size;
+       g_BridgeDispatchTable[ui32Index].err_offset = err_offset;
+#if defined(DEBUG_BRIDGE_KM)
+       g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+       g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+       g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+       g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+#endif
+
+       ui32PrevIndex = ui32Index;
+}
+
+static IMG_INT
+PVRSRVInitSrvConnectBW(IMG_UINT32 ui32BridgeID,
+                                          IMG_VOID *psBridgeIn,
+                                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+        
+       if((OSProcHasPrivSrvInit() == IMG_FALSE) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+       {
+               psRetOUT->eError = PVRSRV_ERROR_SRV_CONNECT_FAILED;
+               return 0;
+       }
+
+#if defined (__linux__)
+       PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+#endif
+       psPerProc->bInitProcess = IMG_TRUE;
+
+       psRetOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVInitSrvDisconnectBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT *psInitSrvDisconnectIN,
+                                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_DISCONNECT);
+
+       if(!psPerProc->bInitProcess)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_SRV_DISCONNECT_FAILED;
+               return 0;
+       }
+
+       psPerProc->bInitProcess = IMG_FALSE;
+
+       PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
+       PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+
+       psRetOUT->eError = PVRSRVFinaliseSystem(psInitSrvDisconnectIN->bInitSuccesful);
+
+       PVRSRVSetInitServerState( PVRSRV_INIT_SERVER_SUCCESSFUL ,
+                               ((psRetOUT->eError == PVRSRV_OK) && (psInitSrvDisconnectIN->bInitSuccesful))
+                               ? IMG_TRUE : IMG_FALSE);
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectWaitBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT *psEventObjectWaitIN,
+                                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hOSEventKM;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_WAIT);
+
+       psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hOSEventKM,
+                                                  psEventObjectWaitIN->hOSEventKM,
+                                                  PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = OSEventObjectWait(hOSEventKM);
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectOpenBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN *psEventObjectOpenIN,
+                                                 PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN *psEventObjectOpenOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_OPEN);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc, 1);
+
+       psEventObjectOpenOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &psEventObjectOpenIN->sEventObject.hOSEventKM,
+                                                  psEventObjectOpenIN->sEventObject.hOSEventKM,
+                                                  PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+
+       if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psEventObjectOpenOUT->eError = OSEventObjectOpen(&psEventObjectOpenIN->sEventObject, &psEventObjectOpenOUT->hOSEvent);
+
+       if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psEventObjectOpenOUT->hOSEvent,
+                                         psEventObjectOpenOUT->hOSEvent,
+                                         PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_MULTI);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectCloseBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE *psEventObjectCloseIN,
+                                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hOSEventKM;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &psEventObjectCloseIN->sEventObject.hOSEventKM,
+                                                  psEventObjectCloseIN->sEventObject.hOSEventKM,
+                                                  PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &hOSEventKM,
+                                                  psEventObjectCloseIN->hOSEventKM,
+                                                  PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = OSEventObjectClose(&psEventObjectCloseIN->sEventObject, hOSEventKM);
+
+       return 0;
+}
+
+
+typedef struct _MODIFY_SYNC_OP_INFO
+{
+       IMG_HANDLE  hResItem;
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+       IMG_UINT32      ui32ModifyFlags;
+       IMG_UINT32      ui32ReadOpsPendingSnapShot;
+       IMG_UINT32      ui32WriteOpsPendingSnapShot;
+} MODIFY_SYNC_OP_INFO;
+
+
+static PVRSRV_ERROR DoQuerySyncOpsSatisfied(MODIFY_SYNC_OP_INFO *psModSyncOpInfo)
+{
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+       psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+       if (!psKernelSyncInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot == psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+          && (psModSyncOpInfo->ui32ReadOpsPendingSnapShot == psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+       {
+#if defined(PDUMP)
+               
+               PDumpComment("Poll for read ops complete to reach value (%u)", psModSyncOpInfo->ui32ReadOpsPendingSnapShot);
+               PDumpMemPolKM(psKernelSyncInfo->psSyncDataMemInfoKM,
+                                                 offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+                                                 psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+                                                 0xFFFFFFFF,
+                                                 PDUMP_POLL_OPERATOR_EQUAL,
+                                                 0,
+                                                 MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+                                                 
+               
+               PDumpComment("Poll for write ops complete to reach value (%u)", psModSyncOpInfo->ui32WriteOpsPendingSnapShot);
+               PDumpMemPolKM(psKernelSyncInfo->psSyncDataMemInfoKM,
+                                                 offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+                                                 psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+                                                 0xFFFFFFFF,
+                                                 PDUMP_POLL_OPERATOR_EQUAL,
+                                                 0,
+                                                 MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+               return PVRSRV_OK;
+       }
+       else
+       {
+               return PVRSRV_ERROR_RETRY;
+       }
+}
+
+static PVRSRV_ERROR DoModifyCompleteSyncOps(MODIFY_SYNC_OP_INFO *psModSyncOpInfo)
+{
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+       psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+       if (!psKernelSyncInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+          || (psModSyncOpInfo->ui32ReadOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+       {
+               return PVRSRV_ERROR_BAD_SYNC_STATE;
+       }
+       
+       
+       if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+       {
+               psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
+       }
+       
+       
+       if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+       {
+               psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(IMG_PVOID            pvParam,
+                                                                                                       IMG_UINT32      ui32Param)
+{
+       MODIFY_SYNC_OP_INFO             *psModSyncOpInfo;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       if (!pvParam)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: invalid parameter"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psModSyncOpInfo = (MODIFY_SYNC_OP_INFO*)pvParam;
+
+       if (psModSyncOpInfo->psKernelSyncInfo)
+       {
+               
+               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+               {
+                       if (DoQuerySyncOpsSatisfied(psModSyncOpInfo) == PVRSRV_OK)
+                       {
+                               goto OpFlushedComplete;
+                       }
+                       PVR_DPF((PVR_DBG_WARNING, "ModifyCompleteSyncOpsCallBack: waiting for current Ops to flush"));
+                       OSSleepms(1);
+               } END_LOOP_UNTIL_TIMEOUT();
+               
+               PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: timeout whilst waiting for current Ops to flush."));
+               PVR_DPF((PVR_DBG_ERROR, "  Write ops pending snapshot = %d, write ops complete = %d",
+                                psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+                                psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32WriteOpsComplete));
+               PVR_DPF((PVR_DBG_ERROR, "  Read ops pending snapshot = %d, write ops complete = %d",
+                                psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+                                psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsComplete));
+               
+               return PVRSRV_ERROR_TIMEOUT;
+               
+       OpFlushedComplete:
+       
+               DoModifyCompleteSyncOps(psModSyncOpInfo);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,      sizeof(MODIFY_SYNC_OP_INFO), (IMG_VOID *)psModSyncOpInfo, 0);
+       
+
+       
+       PVRSRVScheduleDeviceCallbacks();
+
+       return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVCreateSyncInfoModObjBW(IMG_UINT32                                         ui32BridgeID,
+                                                                        IMG_VOID                                           *psBridgeIn,
+                                                                        PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ  *psCreateSyncInfoModObjOUT,
+                                                                        PVRSRV_PER_PROCESS_DATA                                            *psPerProc)
+{
+       MODIFY_SYNC_OP_INFO             *psModSyncOpInfo;
+
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psCreateSyncInfoModObjOUT->eError, psPerProc, 1);
+
+       ASSIGN_AND_EXIT_ON_ERROR(psCreateSyncInfoModObjOUT->eError,
+                         OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         sizeof(MODIFY_SYNC_OP_INFO),
+                         (IMG_VOID **)&psModSyncOpInfo, 0,
+                         "ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
+
+       psModSyncOpInfo->psKernelSyncInfo = IMG_NULL; 
+
+       psCreateSyncInfoModObjOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+                                                                                                                                 &psCreateSyncInfoModObjOUT->hKernelSyncInfoModObj,
+                                                                                                                                 psModSyncOpInfo,
+                                                                                                                                 PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ,
+                                                                                                                                 PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE);
+
+       if (psCreateSyncInfoModObjOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psModSyncOpInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                 RESMAN_TYPE_MODIFY_SYNC_OPS,
+                                                                                                 psModSyncOpInfo,
+                                                                                                 0,
+                                                                                                 &ModifyCompleteSyncOpsCallBack);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psCreateSyncInfoModObjOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVDestroySyncInfoModObjBW(IMG_UINT32                                          ui32BridgeID,
+                                                         PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ          *psDestroySyncInfoModObjIN,
+                                                         PVRSRV_BRIDGE_RETURN                                *psDestroySyncInfoModObjOUT,
+                                                         PVRSRV_PER_PROCESS_DATA                                             *psPerProc)
+{
+       MODIFY_SYNC_OP_INFO             *psModSyncOpInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ);
+
+       psDestroySyncInfoModObjOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                                                                                       (IMG_VOID**)&psModSyncOpInfo,
+                                                                                                                                       psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
+                                                                                                                                       PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+       if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: PVRSRVLookupHandle failed"));
+               return 0;
+       }
+
+       if(psModSyncOpInfo->psKernelSyncInfo != IMG_NULL)
+       {
+               
+               psDestroySyncInfoModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+
+       psDestroySyncInfoModObjOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                                                                                                        psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
+                                                                                                                                        PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+
+       if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: PVRSRVReleaseHandle failed"));
+               return 0;
+       }
+
+       psDestroySyncInfoModObjOUT->eError = ResManFreeResByPtr(psModSyncOpInfo->hResItem);
+       if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: ResManFreeResByPtr failed"));
+               return 0;
+       }
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVModifyPendingSyncOpsBW(IMG_UINT32                                                                        ui32BridgeID,
+                                                     PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS  *psModifySyncOpsIN,
+                                                         PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS     *psModifySyncOpsOUT,
+                                                         PVRSRV_PER_PROCESS_DATA                                       *psPerProc)
+{
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+       MODIFY_SYNC_OP_INFO             *psModSyncOpInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS);
+
+       psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                                                       (IMG_VOID**)&psModSyncOpInfo,
+                                                                                                       psModifySyncOpsIN->hKernelSyncInfoModObj,
+                                                                                                       PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+       if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+               return 0;
+       }
+
+       psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                                                       (IMG_VOID**)&psKernelSyncInfo,
+                                                                                                       psModifySyncOpsIN->hKernelSyncInfo,
+                                                                                                       PVRSRV_HANDLE_TYPE_SYNC_INFO);
+       if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+               return 0;
+       }
+
+       if(psModSyncOpInfo->psKernelSyncInfo)
+       {
+               
+               psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
+               PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo Modification object is not empty"));
+               return 0;
+       }
+
+       
+       psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
+       psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
+       psModSyncOpInfo->ui32ReadOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+       psModSyncOpInfo->ui32WriteOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+       
+
+       psModifySyncOpsOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+       psModifySyncOpsOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+       if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+       {
+               psKernelSyncInfo->psSyncData->ui32WriteOpsPending++;
+       }
+
+       if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+       {
+               psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+       }
+
+       
+       psModifySyncOpsOUT->eError = ResManDissociateRes(psModSyncOpInfo->hResItem,
+                                                                                                        psPerProc->hResManContext);
+
+       if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+               return 0;
+       }
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyCompleteSyncOpsBW(IMG_UINT32                                                       ui32BridgeID,
+                                     PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS         *psModifySyncOpsIN,
+                                         PVRSRV_BRIDGE_RETURN                                                  *psModifySyncOpsOUT,
+                                         PVRSRV_PER_PROCESS_DATA                                               *psPerProc)
+{
+       MODIFY_SYNC_OP_INFO             *psModSyncOpInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS);
+
+       psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                                                       (IMG_VOID**)&psModSyncOpInfo,
+                                                                                                       psModifySyncOpsIN->hKernelSyncInfoModObj,
+                                                                                                       PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+       if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: PVRSRVLookupHandle failed"));
+               return 0;
+       }
+
+       if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
+       {
+               
+               psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+
+       psModifySyncOpsOUT->eError = DoModifyCompleteSyncOps(psModSyncOpInfo);
+
+       if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: DoModifyCompleteSyncOps failed"));
+               return 0;
+       }
+
+       psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
+
+       
+       PVRSRVScheduleDeviceCallbacks();
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToModObjBW(IMG_UINT32                                         ui32BridgeID,
+                                                        PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ                 *psSyncOpsFlushToModObjIN,
+                                                        PVRSRV_BRIDGE_RETURN                                                   *psSyncOpsFlushToModObjOUT,
+                                                        PVRSRV_PER_PROCESS_DATA                                            *psPerProc)
+{
+       MODIFY_SYNC_OP_INFO             *psModSyncOpInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ);
+
+       psSyncOpsFlushToModObjOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                                                                  (IMG_VOID**)&psModSyncOpInfo,
+                                                                                                                  psSyncOpsFlushToModObjIN->hKernelSyncInfoModObj,
+                                                                                                                  PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+       if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToModObjBW: PVRSRVLookupHandle failed"));
+               return 0;
+       }
+
+       if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
+       {
+               
+               psSyncOpsFlushToModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+
+       psSyncOpsFlushToModObjOUT->eError = DoQuerySyncOpsSatisfied(psModSyncOpInfo);
+
+       if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK && psSyncOpsFlushToModObjOUT->eError != PVRSRV_ERROR_RETRY)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToModObjBW: DoQuerySyncOpsSatisfied failed"));
+               return 0;
+       }
+
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToDeltaBW(IMG_UINT32                                         ui32BridgeID,
+                                                       PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA                   *psSyncOpsFlushToDeltaIN,
+                                                       PVRSRV_BRIDGE_RETURN                                                   *psSyncOpsFlushToDeltaOUT,
+                                                       PVRSRV_PER_PROCESS_DATA                                        *psPerProc)
+{
+       PVRSRV_KERNEL_SYNC_INFO         *psSyncInfo;
+       IMG_UINT32 ui32DeltaRead;
+       IMG_UINT32 ui32DeltaWrite;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA);
+
+       psSyncOpsFlushToDeltaOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                                                                 (IMG_VOID**)&psSyncInfo,
+                                                                                                                 psSyncOpsFlushToDeltaIN->hKernelSyncInfo,
+                                                                                                                 PVRSRV_HANDLE_TYPE_SYNC_INFO);
+       if (psSyncOpsFlushToDeltaOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToDeltaBW: PVRSRVLookupHandle failed"));
+               return 0;
+       }
+
+       ui32DeltaRead = psSyncInfo->psSyncData->ui32ReadOpsPending - psSyncInfo->psSyncData->ui32ReadOpsComplete;
+       ui32DeltaWrite = psSyncInfo->psSyncData->ui32WriteOpsPending - psSyncInfo->psSyncData->ui32WriteOpsComplete;
+
+       if (ui32DeltaRead <= psSyncOpsFlushToDeltaIN->ui32Delta && ui32DeltaWrite <= psSyncOpsFlushToDeltaIN->ui32Delta)
+       {
+#if defined(PDUMP)
+               IMG_UINT32 ui32MinimumReadOpsComplete;
+
+               ui32MinimumReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+               if (ui32MinimumReadOpsComplete < psSyncOpsFlushToDeltaIN->ui32Delta)
+               {
+                       ui32MinimumReadOpsComplete = 0;
+               }
+               else
+               {
+                       ui32MinimumReadOpsComplete = ui32MinimumReadOpsComplete - psSyncOpsFlushToDeltaIN->ui32Delta;
+               }
+
+               
+               PDumpComment("Poll for read ops complete to delta (%u)",
+                                        psSyncOpsFlushToDeltaIN->ui32Delta);
+               psSyncOpsFlushToDeltaOUT->eError =
+                       PDumpMemPolKM(psSyncInfo->psSyncDataMemInfoKM,
+                                                 offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+                                                 psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                                 0xFFFFFFFF,
+                                                 PDUMP_POLL_OPERATOR_GREATEREQUAL,
+                                                 0,
+                                                 MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+               
+               PDumpComment("Poll for write ops complete to delta (%u)",
+                                        psSyncOpsFlushToDeltaIN->ui32Delta);
+               psSyncOpsFlushToDeltaOUT->eError =
+                       PDumpMemPolKM(psSyncInfo->psSyncDataMemInfoKM,
+                                                 offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+                                                 psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                                 0xFFFFFFFF,
+                                                 PDUMP_POLL_OPERATOR_GREATEREQUAL,
+                                                 0,
+                                                 MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+               psSyncOpsFlushToDeltaOUT->eError = PVRSRV_OK;
+       }
+       else
+       {
+               psSyncOpsFlushToDeltaOUT->eError = PVRSRV_ERROR_RETRY;
+       }
+
+       return 0;
+}
+
+
+static PVRSRV_ERROR
+FreeSyncInfoCallback(IMG_PVOID pvParam,
+                                        IMG_UINT32     ui32Param)
+{
+       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pvParam;
+
+       eError = PVRSRVFreeSyncInfoKM(psSyncInfo);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+       
+       return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVAllocSyncInfoBW(IMG_UINT32                                         ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO                  *psAllocSyncInfoIN,
+                                         PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO                 *psAllocSyncInfoOUT,
+                                         PVRSRV_PER_PROCESS_DATA                                           *psPerProc)
+{
+       PVRSRV_KERNEL_SYNC_INFO         *psSyncInfo;
+       PVRSRV_ERROR eError;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_HANDLE hDevMemContext;
+               
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SYNC_INFO);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psAllocSyncInfoOUT->eError, psPerProc, 1);
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               (IMG_HANDLE *)&psDeviceNode,
+                                                               psAllocSyncInfoIN->hDevCookie,
+                                                               PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(eError != PVRSRV_OK)
+       {
+               goto allocsyncinfo_errorexit;
+       }
+
+       hDevMemContext = psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+       
+       eError = PVRSRVAllocSyncInfoKM(psDeviceNode,
+                                                                  hDevMemContext,
+                                                                  &psSyncInfo);
+                       
+       if (eError != PVRSRV_OK)
+       {
+               goto allocsyncinfo_errorexit;
+       }
+
+       eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+                                                          &psAllocSyncInfoOUT->hKernelSyncInfo,
+                                                          psSyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO,
+                                                          PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE);
+
+       if(eError != PVRSRV_OK)
+       {
+               goto allocsyncinfo_errorexit_freesyncinfo;
+       }
+
+       psSyncInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                          RESMAN_TYPE_SYNC_INFO,
+                                                                                          psSyncInfo,
+                                                                                          0,
+                                                                                          FreeSyncInfoCallback);
+
+       
+       goto allocsyncinfo_commit;
+       
+       
+ allocsyncinfo_errorexit_freesyncinfo:
+       PVRSRVFreeSyncInfoKM(psSyncInfo);
+
+ allocsyncinfo_errorexit:
+
+       
+ allocsyncinfo_commit:
+       psAllocSyncInfoOUT->eError = eError;
+       COMMIT_HANDLE_BATCH_OR_ERROR(eError, psPerProc);
+               
+       return 0;
+}
+
+
+static IMG_INT
+PVRSRVFreeSyncInfoBW(IMG_UINT32                                          ui32BridgeID,
+                                        PVRSRV_BRIDGE_IN_FREE_SYNC_INFO                     *psFreeSyncInfoIN,
+                                        PVRSRV_BRIDGE_RETURN                                *psFreeSyncInfoOUT,
+                                        PVRSRV_PER_PROCESS_DATA                                             *psPerProc)
+{
+       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       PVRSRV_ERROR eError;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SYNC_INFO);
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               (IMG_VOID**)&psSyncInfo,
+                                                               psFreeSyncInfoIN->hKernelSyncInfo,
+                                                               PVRSRV_HANDLE_TYPE_SYNC_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: PVRSRVLookupHandle failed"));
+               psFreeSyncInfoOUT->eError = eError;
+               return 0;
+       }
+
+       eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                                psFreeSyncInfoIN->hKernelSyncInfo,
+                                                                PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: PVRSRVReleaseHandle failed"));
+               psFreeSyncInfoOUT->eError = eError;
+               return 0;
+       }
+
+       eError = ResManFreeResByPtr(psSyncInfo->hResItem);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: ResManFreeResByPtr failed"));
+               psFreeSyncInfoOUT->eError = eError;
+               return 0;
+       }
+
+       return 0;
+}
+
+
+PVRSRV_ERROR
+CommonBridgeInit(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       PVR_IO_NSTD(ENUM_DEVICES, PVRSRVEnumerateDevicesBW,
+               0, sizeof(PVRSRV_BRIDGE_OUT_ENUMDEVICE),
+               offsetof(PVRSRV_BRIDGE_OUT_ENUMDEVICE, eError));
+       PVR_IO_RW(ACQUIRE_DEVICEINFO, PVRSRVAcquireDeviceDataBW);
+       PVR_IO_INV(RELEASE_DEVICEINFO);
+       PVR_IO_RW(CREATE_DEVMEMCONTEXT, PVRSRVCreateDeviceMemContextBW);
+       PVR_IO_W(DESTROY_DEVMEMCONTEXT, PVRSRVDestroyDeviceMemContextBW);
+       PVR_IO_RW(GET_DEVMEM_HEAPINFO, PVRSRVGetDeviceMemHeapInfoBW);
+       PVR_IO_NSTD(ALLOC_DEVICEMEM, PVRSRVAllocDeviceMemBW,
+               sizeof(PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM),
+               sizeof(PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM),
+               offsetof(PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM, eError));
+       PVR_IO_NSTD(FREE_DEVICEMEM, PVRSRVFreeDeviceMemBW,
+               sizeof(PVRSRV_BRIDGE_IN_FREEDEVICEMEM),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(GETFREE_DEVICEMEM, PVRSRVGetFreeDeviceMemBW,
+               sizeof(PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM),
+               sizeof(PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM),
+               offsetof(PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM, eError));
+       PVR_IO_INV(CREATE_COMMANDQUEUE);
+       PVR_IO_INV(DESTROY_COMMANDQUEUE);
+       PVR_IO_RW(MHANDLE_TO_MMAP_DATA, PVRMMapOSMemHandleToMMapDataBW);
+       PVR_IO_RW(CONNECT_SERVICES, PVRSRVConnectBW);
+       PVR_IO_NSTD(DISCONNECT_SERVICES, PVRSRVDisconnectBW,
+               0, sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_INV(WRAP_DEVICE_MEM);
+       PVR_IO_INV(GET_DEVICEMEMINFO);
+       PVR_IO_INV(RESERVE_DEV_VIRTMEM);
+       PVR_IO_INV(FREE_DEV_VIRTMEM);
+       PVR_IO_INV(MAP_EXT_MEMORY);
+       PVR_IO_INV(UNMAP_EXT_MEMORY);
+       PVR_IO_RW(MAP_DEV_MEMORY, PVRSRVMapDeviceMemoryBW);
+       PVR_IO_W(UNMAP_DEV_MEMORY, PVRSRVUnmapDeviceMemoryBW);
+       PVR_IO_RW(MAP_DEVICECLASS_MEMORY, PVRSRVMapDeviceClassMemoryBW);
+       PVR_IO_W(UNMAP_DEVICECLASS_MEMORY, PVRSRVUnmapDeviceClassMemoryBW);
+       PVR_IO_INV(MAP_MEM_INFO_TO_USER);
+       PVR_IO_INV(UNMAP_MEM_INFO_FROM_USER);
+       PVR_IO_NSTD(EXPORT_DEVICEMEM, PVRSRVExportDeviceMemBW,
+               sizeof(PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM),
+               sizeof(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM),
+               offsetof(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM, eError));
+       PVR_IO_RW(RELEASE_MMAP_DATA, PVRMMapReleaseMMapDataBW);
+       PVR_IO_INV(PROCESS_SIMISR_EVENT);
+       PVR_IO_INV(REGISTER_SIM_PROCESS);
+       PVR_IO_INV(UNREGISTER_SIM_PROCESS);
+       PVR_IO_INV(MAPPHYSTOUSERSPACE);
+       PVR_IO_INV(UNMAPPHYSTOUSERSPACE);
+       PVR_IO_INV(GETPHYSTOUSERSPACEMAP);
+       PVR_IO_INV(GET_FB_STATS);
+       PVR_IO_RW(GET_MISC_INFO, PVRSRVGetMiscInfoBW);
+       PVR_IO_INV(RELEASE_MISC_INFO);
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+       PVR_IO_INV(INIT_3D_OVL_BLT_RES);
+       PVR_IO_INV(DEINIT_3D_OVL_BLT_RES);
+#endif
+
+#if defined(PDUMP)
+       PVR_IO_INV(PDUMP_INIT);
+       PVR_IO_W(PDUMP_MEMPOL, PDumpMemPolBW);
+       PVR_IO_W(PDUMP_DUMPMEM, PDumpMemBW);
+       PVR_IO_NSTD(PDUMP_REG, PDumpRegWithFlagsBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_DUMPREG),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_W(PDUMP_REGPOL, PDumpRegPolBW);
+       PVR_IO_W(PDUMP_COMMENT, PDumpCommentBW);
+       PVR_IO_W(PDUMP_SETFRAME, PDumpSetFrameBW);
+       PVR_IO_R(PDUMP_ISCAPTURING, PDumpIsCaptureFrameBW);
+       PVR_IO_NSTD(PDUMP_DUMPBITMAP, PDumpBitmapBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_BITMAP),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(PDUMP_DUMPREADREG, PDumpReadRegBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_READREG),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_W(PDUMP_SYNCPOL, PDumpSyncPolBW);
+       PVR_IO_W(PDUMP_DUMPSYNC, PDumpSyncDumpBW);
+       PVR_IO_W(PDUMP_DRIVERINFO, PDumpDriverInfoBW);
+       PVR_IO_W(PDUMP_DUMPPDDEVPADDR, PDumpPDDevPAddrBW);
+       PVR_IO_W(PDUMP_CYCLE_COUNT_REG_READ, PDumpCycleCountRegReadBW);
+       PVR_IO_NSTD(PDUMP_STARTINITPHASE, PDumpStartInitPhaseBW,
+               0, sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(PDUMP_STOPINITPHASE, PDumpStopInitPhaseBW,
+               0, sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+#endif 
+       PVR_IO_INV(GET_OEMJTABLE);
+       PVR_IO_NSTD(ENUM_CLASS, PVRSRVEnumerateDCBW,
+               sizeof(PVRSRV_BRIDGE_IN_ENUMCLASS),
+               sizeof(PVRSRV_BRIDGE_OUT_ENUMCLASS),
+               offsetof(PVRSRV_BRIDGE_OUT_ENUMCLASS, eError));
+       PVR_IO_RW(OPEN_DISPCLASS_DEVICE, PVRSRVOpenDCDeviceBW);
+       PVR_IO_W(CLOSE_DISPCLASS_DEVICE, PVRSRVCloseDCDeviceBW);
+       PVR_IO_RW(ENUM_DISPCLASS_FORMATS, PVRSRVEnumDCFormatsBW);
+       PVR_IO_RW(ENUM_DISPCLASS_DIMS, PVRSRVEnumDCDimsBW);
+       PVR_IO_RW(GET_DISPCLASS_SYSBUFFER, PVRSRVGetDCSystemBufferBW);
+       PVR_IO_RW(GET_DISPCLASS_INFO, PVRSRVGetDCInfoBW);
+       PVR_IO_RW(CREATE_DISPCLASS_SWAPCHAIN, PVRSRVCreateDCSwapChainBW);
+       PVR_IO_W(DESTROY_DISPCLASS_SWAPCHAIN, PVRSRVDestroyDCSwapChainBW);
+       PVR_IO_NSTD(SET_DISPCLASS_DSTRECT, PVRSRVSetDCDstRectBW,
+               sizeof(PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SET_DISPCLASS_SRCRECT, PVRSRVSetDCSrcRectBW,
+               sizeof(PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SET_DISPCLASS_DSTCOLOURKEY, PVRSRVSetDCDstColourKeyBW,
+               sizeof(PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SET_DISPCLASS_SRCCOLOURKEY, PVRSRVSetDCSrcColourKeyBW,
+               sizeof(PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_RW(GET_DISPCLASS_BUFFERS, PVRSRVGetDCBuffersBW);
+       PVR_IO_W(SWAP_DISPCLASS_TO_BUFFER, PVRSRVSwapToDCBufferBW);
+       PVR_IO_W(SWAP_DISPCLASS_TO_SYSTEM, PVRSRVSwapToDCSystemBW);
+       PVR_IO_RW(GET_DISPCLASS_FRONT_BUFFER, PVRSRVGetDCFrontBufferBW);
+       PVR_IO_RW(OPEN_BUFFERCLASS_DEVICE, PVRSRVOpenBCDeviceBW);
+       PVR_IO_W(CLOSE_BUFFERCLASS_DEVICE, PVRSRVCloseBCDeviceBW);
+       PVR_IO_RW(GET_BUFFERCLASS_INFO, PVRSRVGetBCInfoBW);
+       PVR_IO_RW(GET_BUFFERCLASS_BUFFER, PVRSRVGetBCBufferBW);
+       PVR_IO_RW(WRAP_EXT_MEMORY, PVRSRVWrapExtMemoryBW);
+       PVR_IO_W(UNWRAP_EXT_MEMORY, PVRSRVUnwrapExtMemoryBW);
+       PVR_IO_RW(ALLOC_SHARED_SYS_MEM, PVRSRVAllocSharedSysMemoryBW);
+       PVR_IO_RW(FREE_SHARED_SYS_MEM, PVRSRVFreeSharedSysMemoryBW);
+       PVR_IO_RW(MAP_MEMINFO_MEM, PVRSRVMapMemInfoMemBW);
+       PVR_IO_RW(GETMMU_PD_DEVPADDR, MMU_GetPDDevPAddrBW);
+       PVR_IO_NSTD(INITSRV_CONNECT, PVRSRVInitSrvConnectBW,
+               0, sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_W(INITSRV_DISCONNECT, PVRSRVInitSrvDisconnectBW);
+       PVR_IO_W(EVENT_OBJECT_WAIT, PVRSRVEventObjectWaitBW);
+       PVR_IO_RW(EVENT_OBJECT_OPEN, PVRSRVEventObjectOpenBW);
+       PVR_IO_W(EVENT_OBJECT_CLOSE, PVRSRVEventObjectCloseBW);
+       PVR_IO_NSTD(CREATE_SYNC_INFO_MOD_OBJ, PVRSRVCreateSyncInfoModObjBW,
+               0, sizeof(PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ),
+               offsetof(PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ, eError));
+       PVR_IO_W(DESTROY_SYNC_INFO_MOD_OBJ, PVRSRVDestroySyncInfoModObjBW);
+       PVR_IO_RW(MODIFY_PENDING_SYNC_OPS, PVRSRVModifyPendingSyncOpsBW);
+       PVR_IO_W(MODIFY_COMPLETE_SYNC_OPS, PVRSRVModifyCompleteSyncOpsBW);
+       PVR_IO_W(SYNC_OPS_FLUSH_TO_MOD_OBJ, PVRSRVSyncOpsFlushToModObjBW);
+       PVR_IO_W(SYNC_OPS_FLUSH_TO_DELTA, PVRSRVSyncOpsFlushToDeltaBW);
+       PVR_IO_RW(ALLOC_SYNC_INFO, PVRSRVAllocSyncInfoBW);
+       PVR_IO_W(FREE_SYNC_INFO, PVRSRVFreeSyncInfoBW);
+#if defined (SUPPORT_SGX)
+       SetSGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_VGX)
+       SetVGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_MSVDX)
+       SetMSVDXDispatchTableEntry();
+#endif
+
+
+       
+       
+       for(i=0;i<BRIDGE_DISPATCH_TABLE_ENTRY_COUNT;i++)
+       {
+               if(!g_BridgeDispatchTable[i].pfFunction)
+               {
+                       g_BridgeDispatchTable[i].pfFunction = &DummyBW;
+#if defined(DEBUG_BRIDGE_KM)
+                       g_BridgeDispatchTable[i].pszIOCName = "_PVRSRV_BRIDGE_DUMMY";
+                       g_BridgeDispatchTable[i].pszFunctionName = "DummyBW";
+                       g_BridgeDispatchTable[i].ui32CallCount = 0;
+                       g_BridgeDispatchTable[i].ui32CopyFromUserTotalBytes = 0;
+                       g_BridgeDispatchTable[i].ui32CopyToUserTotalBytes = 0;
+#endif
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+                                         PVRSRV_BRIDGE_PACKAGE   * psBridgePackageKM)
+{
+
+       IMG_VOID   * psBridgeIn;
+       IMG_VOID   * psBridgeOut;
+       BridgeWrapperFunction pfBridgeHandler;
+       PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *dte;
+       IMG_UINT32   ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+       IMG_INT      err          = -EFAULT;
+       PVRSRV_ERROR pvr_err      = PVRSRV_OK;
+
+       dte = &g_BridgeDispatchTable[ui32BridgeID];
+
+#if defined(DEBUG_TRACE_BRIDGE_KM)
+       pr_debug("pvr %s: %s", __func__, dte->pszIOCName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+       dte->ui32CallCount++;
+       g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+       if (psBridgePackageKM->ui32InBufferSize != dte->in_size ||
+           psBridgePackageKM->ui32OutBufferSize != dte->out_size) {
+               pr_debug("pvr: invalid param size for IOCTL#%d:\n"
+                       "     kern/user in,out: %d/%d,%d/%d\n",
+                       ui32BridgeID,
+                       dte->in_size, psBridgePackageKM->ui32InBufferSize,
+                       dte->out_size, psBridgePackageKM->ui32OutBufferSize);
+               goto return_fault;
+       }
+
+       if(!psPerProc->bInitProcess)
+       {
+               if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+               {
+                       if(!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation failed.  Driver unusable.",
+                                                __FUNCTION__));
+                               goto return_fault;
+                       }
+               }
+               else
+               {
+                       if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING))
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation is in progress",
+                                                __FUNCTION__));
+                               goto return_fault;
+                       }
+                       else
+                       {
+                               
+                               switch(ui32BridgeID)
+                               {
+                                       case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
+                                       case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_DISCONNECT_SERVICES):
+                                       case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_CONNECT):
+                                       case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_DISCONNECT):
+                                               break;
+                                       default:
+                                               PVR_DPF((PVR_DBG_ERROR, "%s: Driver initialisation not completed yet.",
+                                                                __FUNCTION__));
+                                               goto return_fault;
+                               }
+                       }
+               }
+       }
+
+
+
+#if defined(__linux__)
+       {
+               
+               SYS_DATA *psSysData;
+
+               SysAcquireData(&psSysData);
+
+               
+               psBridgeIn = ((ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
+               psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+               
+#if defined(DEBUG)
+               PVR_ASSERT(psBridgePackageKM->ui32InBufferSize < PVRSRV_MAX_BRIDGE_IN_SIZE);
+               PVR_ASSERT(psBridgePackageKM->ui32OutBufferSize < PVRSRV_MAX_BRIDGE_OUT_SIZE);
+#endif
+
+               if(psBridgePackageKM->ui32InBufferSize > 0)
+               {
+                       if(!OSAccessOK(PVR_VERIFY_READ,
+                                                       psBridgePackageKM->pvParamIn,
+                                                       psBridgePackageKM->ui32InBufferSize))
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Invalid pvParamIn pointer", __FUNCTION__));
+                       }
+
+                       if(CopyFromUserWrapper(psPerProc,
+                                                      ui32BridgeID,
+                                                                  psBridgeIn,
+                                                                  psBridgePackageKM->pvParamIn,
+                                                                  psBridgePackageKM->ui32InBufferSize)
+                         != PVRSRV_OK)
+                       {
+                               goto return_fault;
+                       }
+               }
+       }
+#else
+       psBridgeIn  = psBridgePackageKM->pvParamIn;
+       psBridgeOut = psBridgePackageKM->pvParamOut;
+#endif
+
+       if(ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is out if range!",
+                                __FUNCTION__, ui32BridgeID));
+               goto return_fault;
+       }
+       pfBridgeHandler = (BridgeWrapperFunction)dte->pfFunction;
+       err = pfBridgeHandler(ui32BridgeID,
+                                                 psBridgeIn,
+                                                 psBridgeOut,
+                                                 psPerProc);
+       if(err < 0)
+       {
+               goto return_fault;
+       }
+
+
+#if defined(__linux__)
+       
+       if(CopyToUserWrapper(psPerProc,
+                                                ui32BridgeID,
+                                                psBridgePackageKM->pvParamOut,
+                                                psBridgeOut,
+                                                psBridgePackageKM->ui32OutBufferSize)
+          != PVRSRV_OK)
+       {
+               goto return_fault;
+       }
+#endif
+
+       err = 0;
+       if (dte->out_size && dte->err_offset)
+               pvr_err = *(PVRSRV_ERROR *)(((u8 *)psBridgeOut) +
+                         dte->err_offset);
+       else
+               pvr_err = 0;
+return_fault:
+       ReleaseHandleBatch(psPerProc);
+
+       if (err < 0 || pvr_err)
+               pr_err("pvr: %.*s: ioctl#%d failed (err %d, pvr_err %d)\n",
+                       sizeof(psPerProc->name), psPerProc->name,
+                       ui32BridgeID, err, pvr_err);
+
+       return err;
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h b/drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
new file mode 100644 (file)
index 0000000..2b3db21
--- /dev/null
@@ -0,0 +1,261 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_PVR_BRIDGE_H__
+#define __BRIDGED_PVR_BRIDGE_H__
+
+#include "pvr_bridge.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+#define PVRSRV_GET_BRIDGE_ID(X)        _IOC_NR(X)
+#else
+#define PVRSRV_GET_BRIDGE_ID(X)        ((X) - PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST))
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+#ifndef ENOTTY
+#define ENOTTY 25
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+                                       IMG_UINT32 ui32BridgeID,
+                                       IMG_VOID *pvDest,
+                                       IMG_VOID *pvSrc,
+                                       IMG_UINT32 ui32Size);
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+                                 IMG_UINT32 ui32BridgeID,
+                                 IMG_VOID *pvDest,
+                                 IMG_VOID *pvSrc,
+                                 IMG_UINT32 ui32Size);
+#else
+#define CopyFromUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+       OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size)
+#define CopyToUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+       OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size)
+#endif
+
+
+#define ASSIGN_AND_RETURN_ON_ERROR(error, src, res)            \
+       do                                                      \
+       {                                                       \
+               (error) = (src);                                \
+               if ((error) != PVRSRV_OK)                       \
+               {                                               \
+                       return (res);                           \
+               }                                               \
+       } while ((error) != PVRSRV_OK)
+
+#define ASSIGN_AND_EXIT_ON_ERROR(error, src)           \
+       ASSIGN_AND_RETURN_ON_ERROR(error, src, 0)
+
+#if defined (PVR_SECURE_HANDLES)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NewHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+NewHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                       IMG_UINT32 ui32BatchSize)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(!psPerProc->bHandlesBatched);
+
+       eError = PVRSRVNewHandleBatch(psPerProc->psHandleBase, ui32BatchSize);
+
+       if (eError == PVRSRV_OK)
+       {
+               psPerProc->bHandlesBatched = IMG_TRUE;
+       }
+
+       return eError;
+}
+
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)     \
+       ASSIGN_AND_EXIT_ON_ERROR(error, NewHandleBatch(psPerProc, ui32BatchSize))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(CommitHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+CommitHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVR_ASSERT(psPerProc->bHandlesBatched);
+
+       psPerProc->bHandlesBatched = IMG_FALSE;
+
+       return PVRSRVCommitHandleBatch(psPerProc->psHandleBase);
+}
+
+
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)                         \
+       ASSIGN_AND_EXIT_ON_ERROR(error, CommitHandleBatch(psPerProc))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ReleaseHandleBatch)
+#endif
+static INLINE IMG_VOID
+ReleaseHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       if (psPerProc->bHandlesBatched)
+       {
+               psPerProc->bHandlesBatched = IMG_FALSE;
+
+               PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
+       }
+}
+#else
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
+#define ReleaseHandleBatch(psPerProc)
+#endif
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+               IMG_VOID *psBridgeIn,
+               IMG_VOID *psBridgeOut,
+               PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32BridgeID,
+                                                                        IMG_VOID *psBridgeIn,
+                                                                        IMG_VOID *psBridgeOut,
+                                                                        PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+{
+       BridgeWrapperFunction pfFunction;
+       size_t in_size;
+       size_t out_size;
+       off_t err_offset;
+#if defined(DEBUG_BRIDGE_KM)
+       const IMG_CHAR *pszIOCName;
+       const IMG_CHAR *pszFunctionName;
+       IMG_UINT32 ui32CallCount;
+       IMG_UINT32 ui32CopyFromUserTotalBytes;
+       IMG_UINT32 ui32CopyToUserTotalBytes;
+#endif
+}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
+
+#if defined(SUPPORT_VGX) || defined(SUPPORT_MSVDX)
+       #if defined(SUPPORT_VGX)
+               #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_VGX_CMD+1)
+               #define PVRSRV_BRIDGE_LAST_DEVICE_CMD      PVRSRV_BRIDGE_LAST_VGX_CMD
+       #else
+               #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_MSVDX_CMD+1)
+               #define PVRSRV_BRIDGE_LAST_DEVICE_CMD      PVRSRV_BRIDGE_LAST_MSVDX_CMD
+       #endif
+#else
+       #if defined(SUPPORT_SGX)
+               #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+               #define PVRSRV_BRIDGE_LAST_DEVICE_CMD      PVRSRV_BRIDGE_LAST_SGX_CMD
+       #else
+               #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+               #define PVRSRV_BRIDGE_LAST_DEVICE_CMD      PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD
+       #endif
+#endif
+
+extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+                                          const IMG_CHAR *pszIOCName,
+                                          BridgeWrapperFunction pfFunction,
+                                          const IMG_CHAR *pszFunctionName,
+                                          size_t in_size, size_t out_size,
+                                          off_t err_offset);
+
+
+#define __set_table(id, fn, in_size, out_size, err_offset)             \
+       _SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(id), #id,           \
+                               (BridgeWrapperFunction)fn, #fn,         \
+                               in_size, out_size, err_offset)
+
+#define PVR_IO_RW(id, fn)                                              \
+       __set_table(PVRSRV_BRIDGE_##id, fn,                             \
+                   sizeof(PVRSRV_BRIDGE_IN_##id),                      \
+                   sizeof(PVRSRV_BRIDGE_OUT_##id),                     \
+                   offsetof(PVRSRV_BRIDGE_OUT_##id, eError))
+
+#define PVR_IO_R(id, fn)                                               \
+       __set_table(PVRSRV_BRIDGE_##id, fn, 0,                          \
+                   sizeof(PVRSRV_BRIDGE_OUT_##id),                     \
+                   offsetof(PVRSRV_BRIDGE_OUT_##id, eError))
+
+#define PVR_IO_W(id, fn)                                               \
+       __set_table(PVRSRV_BRIDGE_##id, fn,                             \
+                   sizeof(PVRSRV_BRIDGE_IN_##id),                      \
+                   sizeof(PVRSRV_BRIDGE_RETURN),                       \
+                   offsetof(PVRSRV_BRIDGE_RETURN, eError))
+
+#define PVR_IO_NSTD(id, fn, in_size, out_size, err_offset)             \
+       __set_table(PVRSRV_BRIDGE_##id, fn, in_size, out_size, err_offset)
+
+#define PVR_IO_INV(id)                                                 \
+       __set_table(PVRSRV_BRIDGE_##id, DummyBW, 0, 0, 0)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(DEBUG)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_UNREFERENCED_PARAMETER(X)
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
+{
+       IMG_UINT32 ui32IOCTLCount;
+       IMG_UINT32 ui32TotalCopyFromUserBytes;
+       IMG_UINT32 ui32TotalCopyToUserBytes;
+}PVRSRV_BRIDGE_GLOBAL_STATS;
+
+extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+PVRSRV_ERROR CommonBridgeInit(IMG_VOID);
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+                                         PVRSRV_BRIDGE_PACKAGE   * psBridgePackageKM);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_support.c b/drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_support.c
new file mode 100644 (file)
index 0000000..adc9610
--- /dev/null
@@ -0,0 +1,85 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "servicesint.h"
+#include "bridged_support.h"
+
+
+PVRSRV_ERROR
+PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle)
+{
+       IMG_HANDLE hMHandleInt;
+       PVRSRV_HANDLE_TYPE eHandleType;
+       PVRSRV_ERROR eError;
+
+
+       eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
+                                                         &eHandleType,
+                                                         hMHandle);
+       if(eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       switch(eHandleType)
+       {
+#if defined(PVR_SECURE_HANDLES)
+               case PVRSRV_HANDLE_TYPE_MEM_INFO:
+               case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+               case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+               {
+                       PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)hMHandleInt;
+
+                       *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+                       break;
+               }
+               case PVRSRV_HANDLE_TYPE_SYNC_INFO:
+               {
+                       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)hMHandleInt;
+                       PVRSRV_KERNEL_MEM_INFO *psMemInfo = psSyncInfo->psSyncDataMemInfoKM;
+
+                       *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+                       break;
+               }
+               case  PVRSRV_HANDLE_TYPE_SOC_TIMER:
+               {
+                       *phOSMemHandle = (IMG_VOID *)hMHandleInt;
+                       break;
+               }
+#else
+               case  PVRSRV_HANDLE_TYPE_NONE:
+                       *phOSMemHandle = (IMG_VOID *)hMHandleInt;
+                       break;
+#endif
+               default:
+                       return PVRSRV_ERROR_BAD_MAPPING;
+       }
+
+       return PVRSRV_OK;
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_support.h b/drivers/staging/mrst/pvr/services4/srvkm/bridged/bridged_support.h
new file mode 100644 (file)
index 0000000..9785d37
--- /dev/null
@@ -0,0 +1,43 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SUPPORT_H__
+#define __BRIDGED_SUPPORT_H__
+
+#include "handle.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c b/drivers/staging/mrst/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
new file mode 100644 (file)
index 0000000..e02aca8
--- /dev/null
@@ -0,0 +1,2765 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+
+#if defined(SUPPORT_SGX)
+
+#include "services.h"
+#include "pvr_debug.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "power.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+
+#if defined(SUPPORT_MSVDX)
+       #include "msvdx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+#include "pvr_trace_cmd.h"
+
+static IMG_INT
+SGXGetClientInfoBW(IMG_UINT32 ui32BridgeID,
+                                  PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+                                  PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+                                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETCLIENTINFO);
+
+       psGetClientInfoOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psGetClientInfoIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psGetClientInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psGetClientInfoOUT->eError =
+               SGXGetClientInfoKM(hDevCookieInt,
+                                                  &psGetClientInfoOUT->sClientInfo);
+       return 0;
+}
+
+static IMG_INT
+SGXReleaseClientInfoBW(IMG_UINT32 ui32BridgeID,
+                                          PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+                                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+       IMG_HANDLE hDevCookieInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psReleaseClientInfoIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+       PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
+
+       psDevInfo->ui32ClientRefCount--;
+
+       psRetOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXGetInternalDevInfoBW(IMG_UINT32 ui32BridgeID,
+                                               PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+                                               PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+                                               PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO);
+
+       psSGXGetInternalDevInfoOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psSGXGetInternalDevInfoIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psSGXGetInternalDevInfoOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psSGXGetInternalDevInfoOUT->eError =
+               SGXGetInternalDevInfoKM(hDevCookieInt,
+                                                               &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
+
+       
+       psSGXGetInternalDevInfoOUT->eError =
+               PVRSRVAllocHandle(psPerProc->psHandleBase,
+                                                 &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+                                                 psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+                                                 PVRSRV_HANDLE_TYPE_MEM_INFO,
+                                                 PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXDoKickBW(IMG_UINT32 ui32BridgeID,
+                       PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+                       PVRSRV_BRIDGE_RETURN *psRetOUT,
+                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_UINT32 i;
+       IMG_INT ret = 0;
+       IMG_UINT32 ui32NumDstSyncs;
+       IMG_HANDLE *phKernelSyncInfoHandles = IMG_NULL;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psDoKickIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+                                                  psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       if(psDoKickIN->sCCBKick.hTA3DSyncInfo != IMG_NULL)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.hTA3DSyncInfo,
+                                                          psDoKickIN->sCCBKick.hTA3DSyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if(psDoKickIN->sCCBKick.hTASyncInfo != IMG_NULL)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.hTASyncInfo,
+                                                          psDoKickIN->sCCBKick.hTASyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if(psDoKickIN->sCCBKick.h3DSyncInfo != IMG_NULL)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.h3DSyncInfo,
+                                                          psDoKickIN->sCCBKick.h3DSyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+       
+       if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+
+       for(i=0; i<psDoKickIN->sCCBKick.ui32NumTASrcSyncs; i++)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+                                                          psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psDoKickIN->sCCBKick.ui32NumTADstSyncs > SGX_MAX_TA_DST_SYNCS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+
+       for(i=0; i<psDoKickIN->sCCBKick.ui32NumTADstSyncs; i++)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+                                                          psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psDoKickIN->sCCBKick.ui32Num3DSrcSyncs > SGX_MAX_3D_SRC_SYNCS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+
+       for(i=0; i<psDoKickIN->sCCBKick.ui32Num3DSrcSyncs; i++)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+                                                          psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+#else
+       
+       if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+       for(i=0; i<psDoKickIN->sCCBKick.ui32NumSrcSyncs; i++)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+                                                          psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+#endif
+
+       if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+       for (i = 0; i < psDoKickIN->sCCBKick.ui32NumTAStatusVals; i++)
+       {
+               psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+                                                          psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+                                                          PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+                                                          psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > SGX_MAX_3D_STATUS_VALS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+       for(i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++)
+       {
+               psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+                                                          psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+                                                          PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+                                                          psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       ui32NumDstSyncs = psDoKickIN->sCCBKick.ui32NumDstSyncObjects;
+
+       if(ui32NumDstSyncs > 0)
+       {
+               if(!OSAccessOK(PVR_VERIFY_READ,
+                                               psDoKickIN->sCCBKick.pahDstSyncHandles,
+                                               ui32NumDstSyncs * sizeof(IMG_HANDLE)))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: SGXDoKickBW:"
+                                       " Invalid pasDstSyncHandles pointer", __FUNCTION__));
+                       return -EFAULT;
+               }
+
+               psRetOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                                                               ui32NumDstSyncs * sizeof(IMG_HANDLE),
+                                                                               (IMG_VOID **)&phKernelSyncInfoHandles,
+                                                                               0,
+                                                                               "Array of Synchronization Info Handles");
+               if (psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+
+               if(CopyFromUserWrapper(psPerProc,
+                                                       ui32BridgeID,
+                                                       phKernelSyncInfoHandles,
+                                                       psDoKickIN->sCCBKick.pahDstSyncHandles,
+                                                       ui32NumDstSyncs * sizeof(IMG_HANDLE)) != PVRSRV_OK)
+               {
+                       ret = -EFAULT;
+                       goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+               }
+
+               
+               psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles;
+
+               for( i = 0; i < ui32NumDstSyncs; i++)
+               {
+                       psRetOUT->eError =
+                               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                       &psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+                                                                       psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+                                                                       PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+                       if(psRetOUT->eError != PVRSRV_OK)
+                       {
+                               goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+                       }
+
+               }
+
+               psRetOUT->eError =
+                                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                          &psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+                                                                          psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+                                                                          PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+               }
+       }
+
+       psRetOUT->eError =
+               SGXDoKickKM(hDevCookieInt, &psDoKickIN->sCCBKick,
+                           psPerProc);
+
+PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+
+       if(phKernelSyncInfoHandles)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 ui32NumDstSyncs * sizeof(IMG_HANDLE),
+                                 (IMG_VOID *)phKernelSyncInfoHandles,
+                                 0);
+               
+       }
+       return ret;
+}
+
+
+static IMG_INT
+SGXScheduleProcessQueuesBW(IMG_UINT32 ui32BridgeID,
+                       PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+                       PVRSRV_BRIDGE_RETURN *psRetOUT,
+                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psScheduleProcQIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = SGXScheduleProcessQueuesKM(hDevCookieInt);
+
+       return 0;
+}
+
+
+#if defined(TRANSFER_QUEUE)
+static IMG_INT
+SGXSubmitTransferBW(IMG_UINT32 ui32BridgeID,
+                       PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+                       PVRSRV_BRIDGE_RETURN *psRetOUT,
+                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       PVRSRV_TRANSFER_SGX_KICK *psKick;
+       IMG_UINT32 i;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMITTRANSFER);
+       PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+       psKick = &psSubmitTransferIN->sKick;
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psSubmitTransferIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &psKick->hCCBMemInfo,
+                                                  psKick->hCCBMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       if (psKick->hTASyncInfo != IMG_NULL)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psKick->hTASyncInfo,
+                                                          psKick->hTASyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psKick->h3DSyncInfo != IMG_NULL)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psKick->h3DSyncInfo,
+                                                          psKick->h3DSyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psKick->ui32NumSrcSync > SGX_MAX_TRANSFER_SYNC_OPS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+       for (i = 0; i < psKick->ui32NumSrcSync; i++)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psKick->ahSrcSyncInfo[i],
+                                                          psKick->ahSrcSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psKick->ui32NumDstSync > SGX_MAX_TRANSFER_SYNC_OPS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+       for (i = 0; i < psKick->ui32NumDstSync; i++)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psKick->ahDstSyncInfo[i],
+                                                          psKick->ahDstSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, psKick, psPerProc);
+
+       return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
+                       PVRSRV_BRIDGE_IN_SUBMIT2D *psSubmit2DIN,
+                       PVRSRV_BRIDGE_RETURN *psRetOUT,
+                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       PVRSRV_2D_SGX_KICK *psKick;
+       IMG_UINT32 i;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMIT2D);
+       PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psSubmit2DIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psKick = &psSubmit2DIN->sKick;
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &psKick->hCCBMemInfo,
+                                                  psKick->hCCBMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       if (psKick->hTASyncInfo != IMG_NULL)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psKick->hTASyncInfo,
+                                                          psKick->hTASyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psKick->h3DSyncInfo != IMG_NULL)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psKick->h3DSyncInfo,
+                                                          psKick->h3DSyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psKick->ui32NumSrcSync > SGX_MAX_2D_SRC_SYNC_OPS)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+               return 0;
+       }
+       for (i = 0; i < psKick->ui32NumSrcSync; i++)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psKick->ahSrcSyncInfo[i],
+                                                          psKick->ahSrcSyncInfo[i],
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       if (psKick->hDstSyncInfo != IMG_NULL)
+       {
+               psRetOUT->eError =
+                       PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &psKick->hDstSyncInfo,
+                                                          psKick->hDstSyncInfo,
+                                                          PVRSRV_HANDLE_TYPE_SYNC_INFO);
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+       psRetOUT->eError =
+               SGXSubmit2DKM(hDevCookieInt, psKick);
+
+       return 0;
+}
+#endif 
+#endif 
+
+
+static IMG_INT
+SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+                                PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+                                PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hDevMemContextInt = 0;
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+       SGX_MISC_INFO        sMiscInfo;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+                                                       PVRSRV_BRIDGE_SGX_GETMISCINFO);
+
+       psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                       &hDevCookieInt,
+                                                       psSGXGetMiscInfoIN->hDevCookie,
+                                                       PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+       
+       if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
+       {
+               psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               &hDevMemContextInt,
+                                                               psSGXGetMiscInfoIN->psMiscInfo->hDevMemContext,
+                                                               PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+               if(psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+#endif
+       
+       psDeviceNode = hDevCookieInt;
+       PVR_ASSERT(psDeviceNode != IMG_NULL);
+       if (psDeviceNode == IMG_NULL)
+       {
+               return -EFAULT;
+       }
+
+       psDevInfo = psDeviceNode->pvDevice;
+
+       
+       psRetOUT->eError = CopyFromUserWrapper(psPerProc,
+                                                      ui32BridgeID,
+                                                      &sMiscInfo,
+                                                      psSGXGetMiscInfoIN->psMiscInfo,
+                                                      sizeof(SGX_MISC_INFO));
+       if (psRetOUT->eError != PVRSRV_OK)
+       {
+               return -EFAULT;
+       }
+
+       {
+               psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, hDevMemContextInt);
+
+               if (psRetOUT->eError != PVRSRV_OK)
+               {
+                       return 0;
+               }
+       }
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_RESOURCEPROF_MEM_INFO)
+       {
+               NEW_HANDLE_BATCH_OR_ERROR(psRetOUT->eError, psPerProc, 1);
+               if (psRetOUT->eError != PVRSRV_OK)
+               {       /*PVR_LOG(("RESOURCE_PROFILING: batch handle fail\n"));*/
+                       return -EFAULT;
+               }
+               PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                                 &sMiscInfo.uData.sSGXResProfMemInfo.hKernelMemInfo,
+                                                 psDevInfo->psResProfMemInfo,
+                                                 PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+                                                 PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+               COMMIT_HANDLE_BATCH_OR_ERROR(psRetOUT->eError, psPerProc);
+               if (psRetOUT->eError != PVRSRV_OK)
+               {
+                       /*PVR_LOG(("RESOURCE_PROFILING: batch commit fail\n"));*/
+                       return -EFAULT;
+               }
+       }
+#endif
+
+       psRetOUT->eError = CopyToUserWrapper(psPerProc,
+                                            ui32BridgeID,
+                                            psSGXGetMiscInfoIN->psMiscInfo,
+                                            &sMiscInfo,
+                                            sizeof(SGX_MISC_INFO));
+       if (psRetOUT->eError != PVRSRV_OK)
+       {
+               return -EFAULT;
+       }
+       return 0;
+}
+
+
+static IMG_INT
+SGXReadHWPerfCBBW(IMG_UINT32                                                   ui32BridgeID,
+                                 PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB   *psSGXReadHWPerfCBIN,
+                                 PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB  *psSGXReadHWPerfCBOUT,
+                                 PVRSRV_PER_PROCESS_DATA                               *psPerProc)
+{
+       IMG_HANDLE                                      hDevCookieInt;
+       PVRSRV_SGX_HWPERF_CB_ENTRY      *psAllocated;
+       IMG_HANDLE                                      hAllocatedHandle;
+       IMG_UINT32                                      ui32AllocatedSize;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_HWPERF_CB);
+
+       psSGXReadHWPerfCBOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                       &hDevCookieInt,
+                                                       psSGXReadHWPerfCBIN->hDevCookie,
+                                                       PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psSGXReadHWPerfCBOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       ui32AllocatedSize = psSGXReadHWPerfCBIN->ui32ArraySize *
+                                                       sizeof(psSGXReadHWPerfCBIN->psHWPerfCBData[0]);
+       ASSIGN_AND_EXIT_ON_ERROR(psSGXReadHWPerfCBOUT->eError,
+                           OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                           ui32AllocatedSize,
+                           (IMG_VOID **)&psAllocated,
+                           &hAllocatedHandle,
+                                               "Array of Hardware Performance Circular Buffer Data"));
+
+       psSGXReadHWPerfCBOUT->eError = SGXReadHWPerfCBKM(hDevCookieInt,
+                                                                                                        psSGXReadHWPerfCBIN->ui32ArraySize,
+                                                                                                        psAllocated,
+                                                                                                        &psSGXReadHWPerfCBOUT->ui32DataCount,
+                                                                                                        &psSGXReadHWPerfCBOUT->ui32ClockSpeed,
+                                                                                                        &psSGXReadHWPerfCBOUT->ui32HostTimeStamp);
+       if (psSGXReadHWPerfCBOUT->eError == PVRSRV_OK)
+       {
+               psSGXReadHWPerfCBOUT->eError = CopyToUserWrapper(psPerProc,
+                                                                ui32BridgeID,
+                                                                psSGXReadHWPerfCBIN->psHWPerfCBData,
+                                                                psAllocated,
+                                                                ui32AllocatedSize);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         ui32AllocatedSize,
+                         psAllocated,
+                         hAllocatedHandle);
+       
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
+                                 PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       PVRSRV_ERROR eError;
+       IMG_BOOL bDissociateFailed = IMG_FALSE;
+       IMG_BOOL bLookupFailed = IMG_FALSE;
+       IMG_BOOL bReleaseFailed = IMG_FALSE;
+       IMG_HANDLE hDummy;
+       IMG_UINT32 i;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
+
+       if(!psPerProc->bInitProcess)
+       {
+               psRetOUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED;
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psSGXDevInitPart2IN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+#endif
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               &hDummy,
+                                                               psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               &hDummy,
+                                                               psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+
+#if defined(FIX_HW_BRN_29702)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDummy,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+#endif
+
+       for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+       {
+               IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+               if (hHandle == IMG_NULL)
+               {
+                       continue;
+               }
+
+               eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                          &hDummy,
+                                                          hHandle,
+                                                          PVRSRV_HANDLE_TYPE_MEM_INFO);
+               if (eError != PVRSRV_OK)
+               {
+                       bLookupFailed = IMG_TRUE;
+               }
+       }
+
+       if (bLookupFailed)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle lookup failed"));
+               psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+               return 0;
+       }
+
+       
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+
+
+       #if defined(SGX_SUPPORT_HWPROFILING)
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+#endif
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                                                 &psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+                                                                                 psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+                                                                                 PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                                                 &psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+                                                                                 psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+                                                                                 PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+
+#if defined(FIX_HW_BRN_29702)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bLookupFailed = IMG_TRUE;
+       }
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                  &psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+                                                  psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+                                                  PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if (eError != PVRSRV_OK)
+       {
+               bReleaseFailed = IMG_TRUE;
+       }
+#endif
+
+
+       for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+       {
+               IMG_HANDLE *phHandle = &psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+               if (*phHandle == IMG_NULL)
+                       continue;
+
+               eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                                          phHandle,
+                                                          *phHandle,
+                                                          PVRSRV_HANDLE_TYPE_MEM_INFO);
+               if (eError != PVRSRV_OK)
+               {
+                       bReleaseFailed = IMG_TRUE;
+               }
+       }
+
+       if (bReleaseFailed)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed"));
+               psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+               
+               PVR_DBG_BREAK;
+               return 0;
+       }
+
+       
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+
+       
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo);
+       bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+#endif
+
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+
+#if defined(FIX_HW_BRN_29702)
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo);
+       bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo);
+       bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo);
+       bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+       eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo);
+       if (eError != PVRSRV_OK)
+       {
+               bDissociateFailed = IMG_TRUE;
+       }
+#endif
+
+       for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+       {
+               IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+               if (hHandle == IMG_NULL)
+                       continue;
+
+               eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, hHandle);
+               if (eError != PVRSRV_OK)
+               {
+                       bDissociateFailed = IMG_TRUE;
+               }
+       }
+
+       
+       if(bDissociateFailed)
+       {
+               PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+               PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+               PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+               PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+               PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+
+               for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+               {
+                       IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+                       if (hHandle == IMG_NULL)
+                               continue;
+
+                       PVRSRVFreeDeviceMemKM(hDevCookieInt, (PVRSRV_KERNEL_MEM_INFO *)hHandle);
+
+               }
+
+               PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A dissociate failed"));
+
+               psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+
+               
+               PVR_DBG_BREAK;
+               return 0;
+       }
+
+       psRetOUT->eError =
+               DevInitSGXPart2KM(psPerProc,
+                                                 hDevCookieInt,
+                                                 &psSGXDevInitPart2IN->sInitInfo);
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+                                                        PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextIN,
+                                                        PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextOUT,
+                                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hHWRenderContextInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc, 1);
+
+       psSGXRegHWRenderContextOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psSGXRegHWRenderContextIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psSGXRegHWRenderContextOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       hHWRenderContextInt =
+               SGXRegisterHWRenderContextKM(hDevCookieInt,
+                                                                        &psSGXRegHWRenderContextIN->sHWRenderContextDevVAddr,
+                                                                        psPerProc);
+
+       if (hHWRenderContextInt == IMG_NULL)
+       {
+               psSGXRegHWRenderContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+               return 0;
+       }
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psSGXRegHWRenderContextOUT->hHWRenderContext,
+                                         hHWRenderContextInt,
+                                         PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+                                                          PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT *psSGXUnregHWRenderContextIN,
+                                                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hHWRenderContextInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hHWRenderContextInt,
+                                                  psSGXUnregHWRenderContextIN->hHWRenderContext,
+                                                  PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = SGXUnregisterHWRenderContextKM(hHWRenderContextInt);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psSGXUnregHWRenderContextIN->hHWRenderContext,
+                                                       PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+                                                        PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextIN,
+                                                        PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextOUT,
+                                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hHWTransferContextInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc, 1);
+
+       psSGXRegHWTransferContextOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psSGXRegHWTransferContextIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psSGXRegHWTransferContextOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       hHWTransferContextInt =
+               SGXRegisterHWTransferContextKM(hDevCookieInt,
+                                                                          &psSGXRegHWTransferContextIN->sHWTransferContextDevVAddr,
+                                                                          psPerProc);
+
+       if (hHWTransferContextInt == IMG_NULL)
+       {
+               psSGXRegHWTransferContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+               return 0;
+       }
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psSGXRegHWTransferContextOUT->hHWTransferContext,
+                                         hHWTransferContextInt,
+                                         PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+                                                          PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT *psSGXUnregHWTransferContextIN,
+                                                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hHWTransferContextInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hHWTransferContextInt,
+                                                  psSGXUnregHWTransferContextIN->hHWTransferContext,
+                                                  PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = SGXUnregisterHWTransferContextKM(hHWTransferContextInt);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psSGXUnregHWTransferContextIN->hHWTransferContext,
+                                                       PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+       return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXRegisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+                                                        PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextIN,
+                                                        PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextOUT,
+                                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_HANDLE hHW2DContextInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc, 1);
+
+       psSGXRegHW2DContextOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psSGXRegHW2DContextIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psSGXRegHW2DContextOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       hHW2DContextInt =
+               SGXRegisterHW2DContextKM(hDevCookieInt,
+                                                                &psSGXRegHW2DContextIN->sHW2DContextDevVAddr,
+                                                                psPerProc);
+
+       if (hHW2DContextInt == IMG_NULL)
+       {
+               psSGXRegHW2DContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+               return 0;
+       }
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psSGXRegHW2DContextOUT->hHW2DContext,
+                                         hHW2DContextInt,
+                                         PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc);
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+                                                          PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT *psSGXUnregHW2DContextIN,
+                                                          PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hHW2DContextInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hHW2DContextInt,
+                                                  psSGXUnregHW2DContextIN->hHW2DContext,
+                                                  PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError = SGXUnregisterHW2DContextKM(hHW2DContextInt);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                       psSGXUnregHW2DContextIN->hHW2DContext,
+                                                       PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+
+       return 0;
+}
+#endif 
+
+static IMG_INT
+SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET *psSGXFlushHWRenderTargetIN,
+                                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psSGXFlushHWRenderTargetIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr);
+
+       return 0;
+}
+
+static void trace_query_cmd(PVRSRV_PER_PROCESS_DATA *proc, int type,
+                           PVRSRV_KERNEL_SYNC_INFO *si)
+{
+       struct pvr_trcmd_syn *ts;
+       size_t size;
+
+       size = si ? sizeof(*ts) : 0;
+
+       ts = pvr_trcmd_reserve(type, proc->ui32PID, proc->name, size);
+       if (si)
+               pvr_trcmd_set_syn(ts, si);
+
+       pvr_trcmd_commit(ts);
+}
+
+static IMG_INT
+SGX2DQueryBlitsCompleteBW(IMG_UINT32 ui32BridgeID,
+                                                 PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+                                                 PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                                 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_VOID *pvSyncInfo;
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  ps2DQueryBltsCompleteIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+                                                  ps2DQueryBltsCompleteIN->hKernSyncInfo,
+                                                  PVRSRV_HANDLE_TYPE_SYNC_INFO);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+       psRetOUT->eError =
+               SGX2DQueryBlitsCompleteKM(psDevInfo,
+                                                                 (PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo,
+                                                                 ps2DQueryBltsCompleteIN->bWaitForComplete);
+
+       trace_query_cmd(psPerProc, PVR_TRCMD_SGX_QBLT_SYNCHK, pvSyncInfo);
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+                                         PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+                                         PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+                                         PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = IMG_NULL;
+       IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount = 0;
+       IMG_UINT32 i;
+       IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc, PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS + 4);
+
+       psSGXFindSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+       psSGXFindSharedPBDescOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hDevCookieInt,
+                                                  psSGXFindSharedPBDescIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+               goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+       psSGXFindSharedPBDescOUT->eError =
+               SGXFindSharedPBDescKM(psPerProc, hDevCookieInt,
+                                                         psSGXFindSharedPBDescIN->bLockOnFailure,
+                                                         psSGXFindSharedPBDescIN->ui32TotalPBSize,
+                                                         &hSharedPBDesc,
+                                                         &psSharedPBDescKernelMemInfo,
+                                                         &psHWPBDescKernelMemInfo,
+                                                         &psBlockKernelMemInfo,
+                                                         &psHWBlockKernelMemInfo,
+                                                         &ppsSharedPBDescSubKernelMemInfos,
+                                                         &ui32SharedPBDescSubKernelMemInfosCount);
+       if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+               goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+       PVR_ASSERT(ui32SharedPBDescSubKernelMemInfosCount
+                          <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+       psSGXFindSharedPBDescOUT->ui32SharedPBDescSubKernelMemInfoHandlesCount =
+               ui32SharedPBDescSubKernelMemInfosCount;
+
+       if(hSharedPBDesc == IMG_NULL)
+       {
+               psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
+               
+               goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+       }
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                         &psSGXFindSharedPBDescOUT->hSharedPBDesc,
+                                         hSharedPBDesc,
+                                         PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+       
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                         &psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
+                                         psSharedPBDescKernelMemInfo,
+                                         PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                         psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                         &psSGXFindSharedPBDescOUT->hHWPBDescKernelMemInfoHandle,
+                                         psHWPBDescKernelMemInfo,
+                                         PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+                                         PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                         psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                 &psSGXFindSharedPBDescOUT->hBlockKernelMemInfoHandle,
+                                 psBlockKernelMemInfo,
+                                 PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+                                 PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                 psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                 &psSGXFindSharedPBDescOUT->hHWBlockKernelMemInfoHandle,
+                                 psHWBlockKernelMemInfo,
+                                 PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+                                 PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                 psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+
+       for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+       {
+               PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOut =
+                       psSGXFindSharedPBDescOUT;
+
+                       PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+                                                         &psSGXFindSharedPBDescOut->ahSharedPBDescSubKernelMemInfoHandles[i],
+                                                         ppsSharedPBDescSubKernelMemInfos[i],
+                                                         PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+                                                         PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                                         psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle);
+       }
+
+PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT:
+       if (ppsSharedPBDescSubKernelMemInfos != IMG_NULL)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+                                 ppsSharedPBDescSubKernelMemInfos,
+                                 IMG_NULL);
+       }
+
+       if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+       {
+               if(hSharedPBDesc != IMG_NULL)
+               {
+                       SGXUnrefSharedPBDescKM(hSharedPBDesc);
+               }
+       }
+       else
+       {
+               COMMIT_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc);
+       }
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXUnrefSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+                                          PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+                                          PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hSharedPBDesc;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC);
+
+       psSGXUnrefSharedPBDescOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                  &hSharedPBDesc,
+                                                  psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+                                                  PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+       if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psSGXUnrefSharedPBDescOUT->eError =
+               SGXUnrefSharedPBDescKM(hSharedPBDesc);
+
+       if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psSGXUnrefSharedPBDescOUT->eError =
+               PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                  psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+                                                  PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+
+       return 0;
+}
+
+
+static IMG_INT
+SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+                                        PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+                                        PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+                                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+       IMG_UINT32 ui32KernelMemInfoHandlesCount =
+               psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+       IMG_INT ret = 0;
+       IMG_HANDLE *phKernelMemInfoHandles = IMG_NULL;
+       PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = IMG_NULL;
+       IMG_UINT32 i;
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc, 1);
+
+       psSGXAddSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+       PVR_ASSERT(ui32KernelMemInfoHandlesCount
+                          <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               &hDevCookieInt,
+                                                               psSGXAddSharedPBDescIN->hDevCookie,
+                                                               PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(eError != PVRSRV_OK)
+       {
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               (IMG_VOID **)&psSharedPBDescKernelMemInfo,
+                                                               psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+       if(eError != PVRSRV_OK)
+       {
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               (IMG_VOID **)&psHWPBDescKernelMemInfo,
+                                                               psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(eError != PVRSRV_OK)
+       {
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               (IMG_VOID **)&psBlockKernelMemInfo,
+                                                               psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+       if(eError != PVRSRV_OK)
+       {
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                               (IMG_VOID **)&psHWBlockKernelMemInfo,
+                                                               psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_MEM_INFO);
+       if(eError != PVRSRV_OK)
+       {
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+
+       if(!OSAccessOK(PVR_VERIFY_READ,
+                                  psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+                                  ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE)))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:"
+                                " Invalid phKernelMemInfos pointer", __FUNCTION__));
+               ret = -EFAULT;
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+                                 (IMG_VOID **)&phKernelMemInfoHandles,
+                                 0,
+                                 "Array of Handles");
+       if (eError != PVRSRV_OK)
+       {
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       if(CopyFromUserWrapper(psPerProc,
+                                      ui32BridgeID,
+                                      phKernelMemInfoHandles,
+                                                  psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+                                                  ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE))
+          != PVRSRV_OK)
+       {
+               ret = -EFAULT;
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+                                 (IMG_VOID **)&ppsKernelMemInfos,
+                                 0,
+                                 "Array of pointers to Kernel Memory Info");
+       if (eError != PVRSRV_OK)
+       {
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+       {
+               eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                       (IMG_VOID **)&ppsKernelMemInfos[i],
+                                                                       phKernelMemInfoHandles[i],
+                                                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+               if(eError != PVRSRV_OK)
+               {
+                       goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+               }
+       }
+
+       
+        
+       eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                               psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+       PVR_ASSERT(eError == PVRSRV_OK);
+
+        
+       eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                               psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_MEM_INFO);
+       PVR_ASSERT(eError == PVRSRV_OK);
+
+        
+       eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                               psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+       PVR_ASSERT(eError == PVRSRV_OK);
+
+        
+       eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                               psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+                                                               PVRSRV_HANDLE_TYPE_MEM_INFO);
+       PVR_ASSERT(eError == PVRSRV_OK);
+
+       for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+       {
+                
+               eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+                                                                       phKernelMemInfoHandles[i],
+                                                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
+
+       eError = SGXAddSharedPBDescKM(psPerProc, hDevCookieInt,
+                                                                 psSharedPBDescKernelMemInfo,
+                                                                 psHWPBDescKernelMemInfo,
+                                                                 psBlockKernelMemInfo,
+                                                                 psHWBlockKernelMemInfo,
+                                                                 psSGXAddSharedPBDescIN->ui32TotalPBSize,
+                                                                 &hSharedPBDesc,
+                                                                 ppsKernelMemInfos,
+                                                                 ui32KernelMemInfoHandlesCount);
+
+
+       if (eError != PVRSRV_OK)
+       {
+               goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+       }
+
+       PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                 &psSGXAddSharedPBDescOUT->hSharedPBDesc,
+                                 hSharedPBDesc,
+                                 PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+                                 PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT:
+
+       if(phKernelMemInfoHandles)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+                                 (IMG_VOID *)phKernelMemInfoHandles,
+                                 0);
+       }
+       if(ppsKernelMemInfos)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+                                 (IMG_VOID *)ppsKernelMemInfos,
+                                 0);
+       }
+
+       if(ret == 0 && eError == PVRSRV_OK)
+       {
+               COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc);
+       }
+
+       psSGXAddSharedPBDescOUT->eError = eError;
+
+       return ret;
+}
+
+static IMG_INT
+SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
+                                          PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+                                          PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+                                          PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       IMG_UINT32 i;
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT);
+
+       NEW_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+       if(!psPerProc->bInitProcess)
+       {
+               psSGXInfoForSrvinitOUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED;
+               return 0;
+       }
+
+       psSGXInfoForSrvinitOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                                                  psSGXInfoForSrvinitIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psSGXInfoForSrvinitOUT->eError =
+               SGXGetInfoForSrvinitKM(hDevCookieInt,
+                                                          &psSGXInfoForSrvinitOUT->sInitInfo);
+
+       if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       for(i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+       {
+               PVRSRV_HEAP_INFO *psHeapInfo;
+
+               psHeapInfo = &psSGXInfoForSrvinitOUT->sInitInfo.asHeapInfo[i];
+
+               if (psHeapInfo->ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID)
+               {
+                       IMG_HANDLE hDevMemHeapExt;
+
+                       if (psHeapInfo->hDevMemHeap != IMG_NULL)
+                       {
+                               
+                               PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+                                                                 &hDevMemHeapExt,
+                                                                 psHeapInfo->hDevMemHeap,
+                                                                 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+                                                                 PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+                               psHeapInfo->hDevMemHeap = hDevMemHeapExt;
+                       }
+               }
+       }
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc);
+
+       return 0;
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                               PSGX_KICKTA_DUMP_BUFFER psBufferArray,
+                               IMG_UINT32                                              ui32BufferArrayLength,
+                               IMG_BOOL                                                bDumpPolls)
+{
+       IMG_UINT32      i;
+
+       for (i=0; i<ui32BufferArrayLength; i++)
+       {
+               PSGX_KICKTA_DUMP_BUFFER psBuffer;
+               PVRSRV_KERNEL_MEM_INFO  *psCtrlMemInfoKM;
+               IMG_CHAR * pszName;
+               IMG_HANDLE hUniqueTag;
+               IMG_UINT32      ui32Offset;
+
+               psBuffer = &psBufferArray[i];
+               pszName = psBuffer->pszName;
+               if (!pszName)
+               {
+                       pszName = "Nameless buffer";
+               }
+
+               hUniqueTag = MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo);
+
+       #if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+               psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hCtrlKernelMemInfo);
+               ui32Offset =  psBuffer->sCtrlDevVAddr.uiAddr - psCtrlMemInfoKM->sDevVAddr.uiAddr;
+       #else
+               psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM;
+               ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+       #endif
+
+               if (psBuffer->ui32Start <= psBuffer->ui32End)
+               {
+                       if (bDumpPolls)
+                       {
+                               PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+                               PDUMPCBP(psCtrlMemInfoKM,
+                                                ui32Offset,
+                                                psBuffer->ui32Start,
+                                                psBuffer->ui32SpaceUsed,
+                                                psBuffer->ui32BufferSize,
+                                                0,
+                                                MAKEUNIQUETAG(psCtrlMemInfoKM));
+                       }
+
+                       PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName);
+                       PDUMPMEMUM(psPerProc,
+                                        IMG_NULL,
+                                        psBuffer->pvLinAddr,
+                                        (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+                                        psBuffer->ui32Start,
+                                        psBuffer->ui32End - psBuffer->ui32Start,
+                                        0,
+                                        hUniqueTag);
+               }
+               else
+               {
+                       
+
+                       if (bDumpPolls)
+                       {
+                               PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+                               PDUMPCBP(psCtrlMemInfoKM,
+                                                ui32Offset,
+                                                psBuffer->ui32Start,
+                                                psBuffer->ui32BackEndLength,
+                                                psBuffer->ui32BufferSize,
+                                                0,
+                                                MAKEUNIQUETAG(psCtrlMemInfoKM));
+                       }
+                       PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName);
+                       PDUMPMEMUM(psPerProc,
+                                        IMG_NULL,
+                                        psBuffer->pvLinAddr,
+                                        (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+                                        psBuffer->ui32Start,
+                                        psBuffer->ui32BackEndLength,
+                                        0,
+                                        hUniqueTag);
+
+                       if (bDumpPolls)
+                       {
+                               PDUMPMEMPOL(psCtrlMemInfoKM,
+                                                       ui32Offset,
+                                                       0,
+                                                       0xFFFFFFFF,
+                                                       PDUMP_POLL_OPERATOR_NOTEQUAL,
+                                                       0,
+                                                       MAKEUNIQUETAG(psCtrlMemInfoKM));
+
+                               PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+                               PDUMPCBP(psCtrlMemInfoKM,
+                                                ui32Offset,
+                                                0,
+                                                psBuffer->ui32End,
+                                                psBuffer->ui32BufferSize,
+                                                0,
+                                                MAKEUNIQUETAG(psCtrlMemInfoKM));
+                       }
+                       PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName);
+                       PDUMPMEMUM(psPerProc,
+                                        IMG_NULL,
+                                        psBuffer->pvLinAddr,
+                                        (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+                                        0,
+                                        psBuffer->ui32End,
+                                        0,
+                                        hUniqueTag);
+               }
+       }
+}
+static IMG_INT
+SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
+                                  PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+                                  IMG_VOID *psBridgeOut,
+                                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_UINT32 i;
+       SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+       IMG_UINT32 ui32BufferArrayLength =
+               psPDumpBufferArrayIN->ui32BufferArrayLength;
+       IMG_UINT32 ui32BufferArraySize =
+               ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
+       PVRSRV_ERROR eError = PVRSRV_ERROR_TOO_FEW_BUFFERS;
+
+       PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 ui32BufferArraySize,
+                                 (IMG_PVOID *)&psKickTADumpBuffer, 0,
+                                 "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK)
+       {
+               return -ENOMEM;
+       }
+
+       if(CopyFromUserWrapper(psPerProc,
+                                      ui32BridgeID,
+                                                  psKickTADumpBuffer,
+                                                  psPDumpBufferArrayIN->psBufferArray,
+                                                  ui32BufferArraySize) != PVRSRV_OK)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+               
+               return -EFAULT;
+       }
+
+       for(i = 0; i < ui32BufferArrayLength; i++)
+       {
+               IMG_VOID *pvMemInfo;
+
+               eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                       &pvMemInfo,
+                                                                       psKickTADumpBuffer[i].hKernelMemInfo,
+                                                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+                                        "PVRSRVLookupHandle failed (%d)", eError));
+                       break;
+               }
+               psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+               eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                       &pvMemInfo,
+                                                                       psKickTADumpBuffer[i].hCtrlKernelMemInfo,
+                                                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+                                        "PVRSRVLookupHandle failed (%d)", eError));
+                       break;
+               }
+               psKickTADumpBuffer[i].hCtrlKernelMemInfo = pvMemInfo;
+#endif
+       }
+
+       if(eError == PVRSRV_OK)
+       {
+               DumpBufferArray(psPerProc,
+                                               psKickTADumpBuffer,
+                                               ui32BufferArrayLength,
+                                               psPDumpBufferArrayIN->bDumpPolls);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+       
+
+       return 0;
+}
+
+static IMG_INT
+SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+                                  PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *psPDump3DSignatureRegistersIN,
+                                  PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_UINT32 ui32RegisterArraySize =  psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+       IMG_UINT32 *pui32Registers = IMG_NULL;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = IMG_NULL;
+#if defined(SGX_FEATURE_MP)    && defined(FIX_HW_BRN_27270)
+       IMG_UINT32      ui32RegVal = 0;
+#endif
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_INT ret = -EFAULT;
+
+       PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS);
+
+       if (ui32RegisterArraySize == 0)
+       {
+               goto ExitNoError;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+                                                  psPDump3DSignatureRegistersIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+               goto Exit;
+       }
+
+       psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+#if defined(SGX_FEATURE_MP)    && defined(FIX_HW_BRN_27270)
+       
+       ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+                                               psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 ui32RegisterArraySize,
+                                 (IMG_PVOID *)&pui32Registers, 0,
+                                 "Array of Registers") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: OSAllocMem failed"));
+               goto Exit;
+       }
+
+       if(CopyFromUserWrapper(psPerProc,
+                                       ui32BridgeID,
+                                       pui32Registers,
+                                       psPDump3DSignatureRegistersIN->pui32Registers,
+                                       ui32RegisterArraySize) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: CopyFromUserWrapper failed"));
+               goto Exit;
+       }
+
+       PDump3DSignatureRegisters(&psDeviceNode->sDevId,
+                                       psPDump3DSignatureRegistersIN->ui32DumpFrameNum,
+                                       psPDump3DSignatureRegistersIN->bLastFrame,
+                                       pui32Registers,
+                                       psPDump3DSignatureRegistersIN->ui32NumRegisters);
+
+       PDumpSignatureBuffer(&psDeviceNode->sDevId,
+                                                "out.tasig", "TA", 0, 
+                                                psDevInfo->psKernelTASigBufferMemInfo->sDevVAddr,
+                                                psDevInfo->psKernelTASigBufferMemInfo->ui32AllocSize,
+                                                0 );
+       PDumpSignatureBuffer(&psDeviceNode->sDevId,
+                                                "out.3dsig", "3D", 0, 
+                                                psDevInfo->psKernel3DSigBufferMemInfo->sDevVAddr,
+                                                psDevInfo->psKernel3DSigBufferMemInfo->ui32AllocSize,
+                                                0 );
+                                                
+ExitNoError:
+       psRetOUT->eError = PVRSRV_OK;
+       ret = 0;
+Exit:
+       if (pui32Registers != IMG_NULL)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+       }
+
+#if defined(SGX_FEATURE_MP)    && defined(FIX_HW_BRN_27270)
+       if (psDevInfo != IMG_NULL)
+       {
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal,
+                                                       psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+       }
+#endif
+
+       return ret;
+}
+
+static IMG_INT
+SGXPDumpCounterRegistersBW(IMG_UINT32 ui32BridgeID,
+                                  PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS *psPDumpCounterRegistersIN,
+                                  IMG_VOID *psBridgeOut,
+                                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_UINT32 ui32RegisterArraySize =  psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+       IMG_UINT32 *pui32Registers = IMG_NULL;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_INT ret = -EFAULT;
+
+       PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS);
+
+       if (ui32RegisterArraySize == 0)
+       {
+               goto ExitNoError;
+       }
+
+       if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+                                                  psPDumpCounterRegistersIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXPDumpCounterRegistersBW: hDevCookie lookup failed"));
+               ret = -ENOMEM;
+               goto Exit;
+       }
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 ui32RegisterArraySize,
+                                 (IMG_PVOID *)&pui32Registers, 0,
+                                 "Array of Registers") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: OSAllocMem failed"));
+               ret = -ENOMEM;
+               goto Exit;
+       }
+
+       if(CopyFromUserWrapper(psPerProc,
+                                       ui32BridgeID,
+                                       pui32Registers,
+                                       psPDumpCounterRegistersIN->pui32Registers,
+                                       ui32RegisterArraySize) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: CopyFromUserWrapper failed"));
+               goto Exit;
+       }
+
+       PDumpCounterRegisters(&psDeviceNode->sDevId,
+                                       psPDumpCounterRegistersIN->ui32DumpFrameNum,
+                                       psPDumpCounterRegistersIN->bLastFrame,
+                                       pui32Registers,
+                                       psPDumpCounterRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+       ret = 0;
+Exit:
+       if (pui32Registers != IMG_NULL)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+       }
+
+       return ret;
+}
+
+static IMG_INT
+SGXPDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+                                  PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *psPDumpTASignatureRegistersIN,
+                                  PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       IMG_UINT32 ui32RegisterArraySize =  psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+       IMG_UINT32 *pui32Registers = IMG_NULL;
+#if defined(SGX_FEATURE_MP)    && defined(FIX_HW_BRN_27270)
+       PVRSRV_SGXDEV_INFO      *psDevInfo = IMG_NULL;
+       IMG_UINT32      ui32RegVal = 0;
+#endif
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_INT ret = -EFAULT;
+
+       PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS);
+
+       if (ui32RegisterArraySize == 0)
+       {
+               goto ExitNoError;
+       }
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+                                                  psPDumpTASignatureRegistersIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+               goto Exit;
+       }
+
+#if defined(SGX_FEATURE_MP)    && defined(FIX_HW_BRN_27270)
+
+       psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+       
+       ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+                                               psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 ui32RegisterArraySize,
+                                 (IMG_PVOID *)&pui32Registers, 0,
+                                 "Array of Registers") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: OSAllocMem failed"));
+               ret = -ENOMEM;
+               goto Exit;
+       }
+
+       if(CopyFromUserWrapper(psPerProc,
+                                       ui32BridgeID,
+                                       pui32Registers,
+                                       psPDumpTASignatureRegistersIN->pui32Registers,
+                                       ui32RegisterArraySize) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: CopyFromUserWrapper failed"));
+               goto Exit;
+       }
+
+       PDumpTASignatureRegisters(&psDeviceNode->sDevId,
+                                       psPDumpTASignatureRegistersIN->ui32DumpFrameNum,
+                                       psPDumpTASignatureRegistersIN->ui32TAKickCount,
+                                       psPDumpTASignatureRegistersIN->bLastFrame,
+                                       pui32Registers,
+                                       psPDumpTASignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+       psRetOUT->eError = PVRSRV_OK;
+       ret = 0;
+Exit:
+       if (pui32Registers != IMG_NULL)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+       }
+
+#if defined(SGX_FEATURE_MP)    && defined(FIX_HW_BRN_27270)
+       if (psDevInfo != IMG_NULL)
+       {
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal,
+                                                       psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+       }
+#endif
+
+       return ret;
+}
+static IMG_INT
+SGXPDumpHWPerfCBBW(IMG_UINT32                                          ui32BridgeID,
+                                  PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB      *psPDumpHWPerfCBIN,
+                                  PVRSRV_BRIDGE_RETURN                         *psRetOUT,
+                                  PVRSRV_PER_PROCESS_DATA                      *psPerProc)
+{
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined(__linux__)
+       PVRSRV_SGXDEV_INFO      *psDevInfo;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+                                                  psPDumpHWPerfCBIN->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       psDevInfo = psDeviceNode->pvDevice;
+
+       PDumpHWPerfCBKM(&psDeviceNode->sDevId,
+                                       &psPDumpHWPerfCBIN->szFileName[0],
+                                       psPDumpHWPerfCBIN->ui32FileOffset,
+                                       psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr,
+                                       psDevInfo->psKernelHWPerfCBMemInfo->ui32AllocSize,
+                                       psPDumpHWPerfCBIN->ui32PDumpFlags);
+
+       return 0;
+#else
+       PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+       PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+       PVR_UNREFERENCED_PARAMETER(psRetOUT);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+       return 0;
+#endif 
+#else
+       PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+       PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+       PVR_UNREFERENCED_PARAMETER(psRetOUT);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+       return -EFAULT;
+#endif 
+}
+
+
+static IMG_INT
+SGXPDumpSaveMemBW(IMG_UINT32                                           ui32BridgeID,
+                                 PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM        *psPDumpSaveMem,
+                                 PVRSRV_BRIDGE_RETURN                          *psRetOUT,
+                                 PVRSRV_PER_PROCESS_DATA                       *psPerProc)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM);
+
+       psRetOUT->eError =
+               PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+                                                  psPDumpSaveMem->hDevCookie,
+                                                  PVRSRV_HANDLE_TYPE_DEV_NODE);
+       if(psRetOUT->eError != PVRSRV_OK)
+       {
+               return 0;
+       }
+
+       PDumpSaveMemKM(&psDeviceNode->sDevId,
+                                  &psPDumpSaveMem->szFileName[0],
+                                  psPDumpSaveMem->ui32FileOffset,
+                                  psPDumpSaveMem->sDevVAddr,
+                                  psPDumpSaveMem->ui32Size,
+                                  psPDumpSaveMem->ui32DataMaster,
+                                  psPDumpSaveMem->ui32PDumpFlags);
+       return 0;
+}
+
+#endif 
+
+
+   
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
+{
+       PVR_IO_NSTD(SGX_GETCLIENTINFO, SGXGetClientInfoBW,
+               sizeof(PVRSRV_BRIDGE_IN_GETCLIENTINFO),
+               sizeof(PVRSRV_BRIDGE_OUT_GETCLIENTINFO),
+               offsetof(PVRSRV_BRIDGE_OUT_GETCLIENTINFO, eError));
+       PVR_IO_NSTD(SGX_RELEASECLIENTINFO, SGXReleaseClientInfoBW,
+               sizeof(PVRSRV_BRIDGE_IN_RELEASECLIENTINFO),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SGX_GETINTERNALDEVINFO, SGXGetInternalDevInfoBW,
+               sizeof(PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO),
+               sizeof(PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO),
+               offsetof(PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO, eError));
+       PVR_IO_NSTD(SGX_DOKICK, SGXDoKickBW,
+               sizeof(PVRSRV_BRIDGE_IN_DOKICK),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SGX_GETPHYSPAGEADDR, DummyBW,
+               sizeof(PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR),
+               sizeof(PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR),
+               offsetof(PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR, eError));
+       PVR_IO_INV(SGX_READREGISTRYDWORD);
+       PVR_IO_NSTD(SGX_2DQUERYBLTSCOMPLETE, SGX2DQueryBlitsCompleteBW,
+               sizeof(PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_INV(SGX_GETMMUPDADDR);
+
+#if defined(TRANSFER_QUEUE)
+       PVR_IO_NSTD(SGX_SUBMITTRANSFER, SGXSubmitTransferBW,
+               sizeof(PVRSRV_BRIDGE_IN_SUBMITTRANSFER),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+#endif
+       PVR_IO_NSTD(SGX_GETMISCINFO, SGXGetMiscInfoBW,
+               sizeof(PVRSRV_BRIDGE_IN_SGXGETMISCINFO),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SGXINFO_FOR_SRVINIT, SGXGetInfoForSrvinitBW,
+               sizeof(PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT),
+               sizeof(PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT),
+               offsetof(PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT, eError));
+       PVR_IO_NSTD(SGX_DEVINITPART2, SGXDevInitPart2BW,
+               sizeof(PVRSRV_BRIDGE_IN_SGXDEVINITPART2),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SGX_FINDSHAREDPBDESC, SGXFindSharedPBDescBW,
+               sizeof(PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC),
+               sizeof(PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC),
+               offsetof(PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC, eError));
+       PVR_IO_NSTD(SGX_UNREFSHAREDPBDESC, SGXUnrefSharedPBDescBW,
+               sizeof(PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC),
+               sizeof(PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC),
+               offsetof(PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC, eError));
+       PVR_IO_NSTD(SGX_ADDSHAREDPBDESC, SGXAddSharedPBDescBW,
+               sizeof(PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC),
+               sizeof(PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC),
+               offsetof(PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC, eError));
+       PVR_IO_RW(SGX_REGISTER_HW_RENDER_CONTEXT, SGXRegisterHWRenderContextBW);
+       PVR_IO_W(SGX_FLUSH_HW_RENDER_TARGET, SGXFlushHWRenderTargetBW);
+       PVR_IO_W(SGX_UNREGISTER_HW_RENDER_CONTEXT, SGXUnregisterHWRenderContextBW);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+       PVR_IO_NSTD(SGX_SUBMIT2D, SGXSubmit2DBW,
+               sizeof(PVRSRV_BRIDGE_IN_SUBMIT2D),
+               sizeof(PVRSRV_BRIDGE_OUT_SUBMIT2D),
+               offsetof(PVRSRV_BRIDGE_OUT_SUBMIT2D, eError));
+       PVR_IO_NSTD(SGX_REGISTER_HW_2D_CONTEXT, SGXRegisterHW2DContextBW,
+               sizeof(PVRSRV_BRIDGE_IN_REGISTER_HW_2D_CONTEXT),
+               sizeof(PVRSRV_BRIDGE_OUT_REGISTER_HW_2D_CONTEXT),
+               offsetof(PVRSRV_BRIDGE_OUT_REGISTER_HW_2D_CONTEXT, eError));
+       PVR_IO_NSTD(SGX_UNREGISTER_HW_2D_CONTEXT, SGXUnregisterHW2DContextBW,
+               sizeof(PVRSRV_BRIDGE_IN_UNREGISTER_HW_2D_CONTEXT),
+               sizeof(PVRSRV_BRIDGE_OUT_UNREGISTER_HW_2D_CONTEXT),
+               offsetof(PVRSRV_BRIDGE_OUT_UNREGISTER_HW_2D_CONTEXT, eError));
+#endif
+       PVR_IO_RW(SGX_REGISTER_HW_TRANSFER_CONTEXT, SGXRegisterHWTransferContextBW);
+       PVR_IO_W(SGX_UNREGISTER_HW_TRANSFER_CONTEXT, SGXUnregisterHWTransferContextBW);
+       PVR_IO_W(SGX_SCHEDULE_PROCESS_QUEUES, SGXScheduleProcessQueuesBW);
+       PVR_IO_RW(SGX_READ_HWPERF_CB, SGXReadHWPerfCBBW);
+
+#if defined(PDUMP)
+       PVR_IO_NSTD(SGX_PDUMP_BUFFER_ARRAY, SGXPDumpBufferArrayBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY), 0, 0);
+       PVR_IO_NSTD(SGX_PDUMP_3D_SIGNATURE_REGISTERS, SGXPDump3DSignatureRegistersBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SGX_PDUMP_COUNTER_REGISTERS, SGXPDumpCounterRegistersBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS), 0, 0);
+       PVR_IO_NSTD(SGX_PDUMP_TA_SIGNATURE_REGISTERS, SGXPDumpTASignatureRegistersBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SGX_PDUMP_HWPERFCB, SGXPDumpHWPerfCBBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+       PVR_IO_NSTD(SGX_PDUMP_SAVEMEM, SGXPDumpSaveMemBW,
+               sizeof(PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM),
+               sizeof(PVRSRV_BRIDGE_RETURN),
+               offsetof(PVRSRV_BRIDGE_RETURN, eError));
+#endif
+}
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h b/drivers/staging/mrst/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
new file mode 100644 (file)
index 0000000..23f3600
--- /dev/null
@@ -0,0 +1,42 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SGX_BRIDGE_H__
+#define __BRIDGED_SGX_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/.gitignore b/drivers/staging/mrst/pvr/services4/srvkm/common/.gitignore
new file mode 100644 (file)
index 0000000..2f89523
--- /dev/null
@@ -0,0 +1,5 @@
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+*.o
+*.o.cmd
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/buffer_manager.c b/drivers/staging/mrst/pvr/services4/srvkm/common/buffer_manager.c
new file mode 100644 (file)
index 0000000..0ea9c80
--- /dev/null
@@ -0,0 +1,2091 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "sysconfig.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "lists.h"
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags);
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping);
+static IMG_BOOL
+BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize,
+                                       IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
+                                       IMG_UINT32 uFlags, IMG_UINTPTR_T *pBase);
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+                               BM_MAPPING *pMapping,
+                               IMG_SIZE_T *pActualSize,
+                               IMG_UINT32 uFlags,
+                               IMG_UINT32 dev_vaddr_alignment,
+                               IMG_DEV_VIRTADDR *pDevVAddr);
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping);
+
+static IMG_BOOL
+AllocMemory (BM_CONTEXT                                *pBMContext,
+                               BM_HEAP                         *psBMHeap,
+                               IMG_DEV_VIRTADDR        *psDevVAddr,
+                               IMG_SIZE_T                      uSize,
+                               IMG_UINT32                      uFlags,
+                               IMG_UINT32                      uDevVAddrAlignment,
+                               BM_BUF                          *pBuf)
+{
+       BM_MAPPING                      *pMapping;
+       IMG_UINTPTR_T           uOffset;
+       RA_ARENA                        *pArena = IMG_NULL;
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "AllocMemory (uSize=0x%x, uFlags=0x%x, align=0x%x)",
+                         uSize, uFlags, uDevVAddrAlignment));
+
+       
+
+
+       if(uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+       {
+               if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+               {
+                       
+                       PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
+                       return IMG_FALSE;
+               }
+
+               
+
+               
+               if(psBMHeap->ui32Attribs
+                  &    (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+                  |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+               {
+                       
+                       pArena = psBMHeap->pImportArena;
+                       PVR_ASSERT(psBMHeap->sDevArena.psDeviceMemoryHeapInfo->ui32Attribs & PVRSRV_MEM_RAM_BACKED_ALLOCATION);
+               }
+               else
+               {
+                       PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: backing store type doesn't match heap"));
+                       return IMG_FALSE;
+               }
+
+               
+               if (!RA_Alloc(pArena,
+                                         uSize,
+                                         IMG_NULL,
+                                         (IMG_VOID*) &pMapping,
+                                         uFlags,
+                                         uDevVAddrAlignment,
+                                         0,
+                                         (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
+                       return IMG_FALSE;
+               }
+
+               uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
+               if(pMapping->CpuVAddr)
+               {
+                       pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
+               }
+               else
+               {
+                       pBuf->CpuVAddr = IMG_NULL;
+               }
+
+               if(uSize == pMapping->uSize)
+               {
+                       pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+               }
+               else
+               {
+                       if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+                                                                uOffset,
+                                                                uSize,
+                                                                psBMHeap->ui32Attribs,
+                                                                &pBuf->hOSMemHandle)!=PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSGetSubMemHandle FAILED"));
+                               return IMG_FALSE;
+                       }
+               }
+
+               
+               pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
+
+               if(uFlags & PVRSRV_MEM_ZERO)
+               {
+                       if(!ZeroBuf(pBuf, pMapping, uSize, psBMHeap->ui32Attribs | uFlags))
+                       {
+                               return IMG_FALSE;
+                       }
+               }
+       }
+       else
+       {
+               if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+               {
+                       
+                       PVR_ASSERT(psDevVAddr != IMG_NULL);
+
+                       if (psDevVAddr == IMG_NULL)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "AllocMemory: invalid parameter - psDevVAddr"));
+                               return IMG_FALSE;
+                       }
+
+                       
+                       pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+                                                                                                       uSize,
+                                                                                                       IMG_NULL,
+                                                                                                       PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
+                                                                                                       uDevVAddrAlignment,
+                                                                                                       psDevVAddr);
+
+                       
+                       pBuf->DevVAddr = *psDevVAddr;
+               }
+               else
+               {
+                       
+
+                       
+                       pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+                                                                                                       uSize,
+                                                                                                       IMG_NULL,
+                                                                                                       0,
+                                                                                                       uDevVAddrAlignment,
+                                                                                                       &pBuf->DevVAddr);
+               }
+
+               
+               if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                                       sizeof (struct _BM_MAPPING_),
+                                                       (IMG_PVOID *)&pMapping, IMG_NULL,
+                                                       "Buffer Manager Mapping") != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSAllocMem(0x%x) FAILED", sizeof(*pMapping)));
+                       return IMG_FALSE;
+               }
+
+               
+               pBuf->CpuVAddr = IMG_NULL;
+               pBuf->hOSMemHandle = 0;
+               pBuf->CpuPAddr.uiAddr = 0;
+
+               
+               pMapping->CpuVAddr = IMG_NULL;
+               pMapping->CpuPAddr.uiAddr = 0;
+               pMapping->DevVAddr = pBuf->DevVAddr;
+               pMapping->psSysAddr = IMG_NULL;
+               pMapping->uSize = uSize;
+               pMapping->hOSMemHandle = 0;
+       }
+
+       
+       pMapping->pArena = pArena;
+
+       pMapping->psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+       pMapping->pBMContext = psBMHeap->pBMContext;
+       pMapping->pBMHeap = psBMHeap;
+       pBuf->pMapping = pMapping;
+
+       
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                               "AllocMemory: pMapping=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
+                               (IMG_UINTPTR_T)pMapping,
+                               pMapping->DevVAddr.uiAddr,
+                               (IMG_UINTPTR_T)pMapping->CpuVAddr,
+                               pMapping->CpuPAddr.uiAddr,
+                               pMapping->uSize));
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                               "AllocMemory: pBuf=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
+                               (IMG_UINTPTR_T)pBuf,
+                               pBuf->DevVAddr.uiAddr,
+                               (IMG_UINTPTR_T)pBuf->CpuVAddr,
+                               pBuf->CpuPAddr.uiAddr,
+                               uSize));
+
+       
+       PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
+
+       return IMG_TRUE;
+}
+
+
+static IMG_BOOL
+WrapMemory (BM_HEAP *psBMHeap,
+                       IMG_SIZE_T uSize,
+                       IMG_SIZE_T ui32BaseOffset,
+                       IMG_BOOL bPhysContig,
+                       IMG_SYS_PHYADDR *psAddr,
+                       IMG_VOID *pvCPUVAddr,
+                       IMG_UINT32 uFlags,
+                       BM_BUF *pBuf)
+{
+       IMG_DEV_VIRTADDR DevVAddr = {0};
+       BM_MAPPING *pMapping;
+       IMG_BOOL bResult;
+       IMG_SIZE_T const ui32PageSize = HOST_PAGESIZE();
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, bPhysContig=0x%x, pvCPUVAddr = 0x%08x, flags=0x%x)",
+                         (IMG_UINTPTR_T)psBMHeap, uSize, ui32BaseOffset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));
+
+       PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
+       
+       PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0);
+
+       uSize += ui32BaseOffset;
+       uSize = HOST_PAGEALIGN (uSize);
+
+       
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof(*pMapping),
+                                               (IMG_PVOID *)&pMapping, IMG_NULL,
+                                               "Mocked-up mapping") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",sizeof(*pMapping)));
+               return IMG_FALSE;
+       }
+
+       OSMemSet(pMapping, 0, sizeof (*pMapping));
+
+       pMapping->uSize = uSize;
+       pMapping->pBMHeap = psBMHeap;
+       pMapping->psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+       pMapping->pBMContext = psBMHeap->pBMContext;
+
+       if(pvCPUVAddr)
+       {
+               pMapping->CpuVAddr = pvCPUVAddr;
+
+               if (bPhysContig)
+               {
+                       pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
+                       pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+                       if(OSRegisterMem(pMapping->CpuPAddr,
+                                                       pMapping->CpuVAddr,
+                                                       pMapping->uSize,
+                                                       uFlags,
+                                                       &pMapping->hOSMemHandle) != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSRegisterMem Phys=0x%08X, Size=%d) failed",
+                                       pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+                               goto fail_cleanup;
+                       }
+               }
+               else
+               {
+                       pMapping->eCpuMemoryOrigin = hm_wrapped_scatter_virtaddr;
+                       pMapping->psSysAddr = psAddr;
+
+                       if(OSRegisterDiscontigMem(pMapping->psSysAddr,
+                                                       pMapping->CpuVAddr,
+                                                       pMapping->uSize,
+                                                       uFlags,
+                                                       &pMapping->hOSMemHandle) != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSRegisterDiscontigMem Size=%d) failed",
+                                       pMapping->uSize));
+                               goto fail_cleanup;
+                       }
+               }
+       }
+       else
+       {
+               if (bPhysContig)
+               {
+                       pMapping->eCpuMemoryOrigin = hm_wrapped;
+                       pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+                       if(OSReservePhys(pMapping->CpuPAddr,
+                                                        pMapping->uSize,
+                                                        uFlags,
+                                                        &pMapping->CpuVAddr,
+                                                        &pMapping->hOSMemHandle) != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSReservePhys Phys=0x%08X, Size=%d) failed",
+                                       pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+                               goto fail_cleanup;
+                       }
+               }
+               else
+               {
+                       pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
+                       pMapping->psSysAddr = psAddr;
+
+                       if(OSReserveDiscontigPhys(pMapping->psSysAddr,
+                                                        pMapping->uSize,
+                                                        uFlags,
+                                                        &pMapping->CpuVAddr,
+                                                        &pMapping->hOSMemHandle) != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSReserveDiscontigPhys Size=%d) failed",
+                                       pMapping->uSize));
+                               goto fail_cleanup;
+                       }
+               }
+       }
+
+       
+       bResult = DevMemoryAlloc(psBMHeap->pBMContext,
+                                                        pMapping,
+                                                        IMG_NULL,
+                                                        uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+                                                        IMG_CAST_TO_DEVVADDR_UINT(ui32PageSize),
+                                                        &DevVAddr);
+       if (!bResult)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "WrapMemory: DevMemoryAlloc(0x%x) failed",
+                               pMapping->uSize));
+               goto fail_cleanup;
+       }
+
+       
+       pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
+       if(!ui32BaseOffset)
+       {
+               pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+       }
+       else
+       {
+               if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+                                                        ui32BaseOffset,
+                                                        (pMapping->uSize-ui32BaseOffset),
+                                                        uFlags,
+                                                        &pBuf->hOSMemHandle)!=PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSGetSubMemHandle failed"));
+                       goto fail_cleanup;
+               }
+       }
+       if(pMapping->CpuVAddr)
+       {
+               pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + ui32BaseOffset);
+       }
+       pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + IMG_CAST_TO_DEVVADDR_UINT(ui32BaseOffset);
+
+       if(uFlags & PVRSRV_MEM_ZERO)
+       {
+               if(!ZeroBuf(pBuf, pMapping, uSize, uFlags))
+               {
+                       return IMG_FALSE;
+               }
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr));
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                               "WrapMemory: DevV=%08X CpuP=%08X uSize=0x%x",
+                               pMapping->DevVAddr.uiAddr, pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                               "WrapMemory: DevV=%08X CpuP=%08X uSize=0x%x",
+                               pBuf->DevVAddr.uiAddr, pBuf->CpuPAddr.uiAddr, uSize));
+
+       pBuf->pMapping = pMapping;
+       return IMG_TRUE;
+
+fail_cleanup:
+       if(ui32BaseOffset && pBuf->hOSMemHandle)
+       {
+               OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);
+       }
+
+       if(pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+       {
+               switch(pMapping->eCpuMemoryOrigin)
+               {
+                       case hm_wrapped:
+                               OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+                               break;
+                       case hm_wrapped_virtaddr:
+                               OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+                               break;
+                       case hm_wrapped_scatter:
+                               OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+                               break;
+                       case hm_wrapped_scatter_virtaddr:
+                               OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+                               break;
+                       default:
+                               break;
+               }
+
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+       
+
+       return IMG_FALSE;
+}
+
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags)
+{
+       IMG_VOID *pvCpuVAddr;
+
+       if(pBuf->CpuVAddr)
+       {
+               OSMemSet(pBuf->CpuVAddr, 0, ui32Bytes);
+       }
+       else if(pMapping->eCpuMemoryOrigin == hm_contiguous
+                       || pMapping->eCpuMemoryOrigin == hm_wrapped)
+       {
+               pvCpuVAddr = OSMapPhysToLin(pBuf->CpuPAddr,
+                                                                       ui32Bytes,
+                                                                       PVRSRV_HAP_KERNEL_ONLY
+                                                                       | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+                                                                       IMG_NULL);
+               if(!pvCpuVAddr)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin for contiguous buffer failed"));
+                       return IMG_FALSE;
+               }
+               OSMemSet(pvCpuVAddr, 0, ui32Bytes);
+               OSUnMapPhysToLin(pvCpuVAddr,
+                                                ui32Bytes,
+                                                PVRSRV_HAP_KERNEL_ONLY
+                                                | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+                                                IMG_NULL);
+       }
+       else
+       {
+               IMG_SIZE_T ui32BytesRemaining = ui32Bytes;
+               IMG_SIZE_T ui32CurrentOffset = 0;
+               IMG_CPU_PHYADDR CpuPAddr;
+
+               
+               PVR_ASSERT(pBuf->hOSMemHandle);
+
+               while(ui32BytesRemaining > 0)
+               {
+                       IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE());
+                       CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset);
+                       
+                       if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1))
+                       {
+                               ui32BlockBytes =
+                                       MIN(ui32BytesRemaining, (IMG_UINT32)(HOST_PAGEALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr));
+                       }
+
+                       pvCpuVAddr = OSMapPhysToLin(CpuPAddr,
+                                                                               ui32BlockBytes,
+                                                                               PVRSRV_HAP_KERNEL_ONLY
+                                                                               | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+                                                                               IMG_NULL);
+                       if(!pvCpuVAddr)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin while zeroing non-contiguous memory FAILED"));
+                               return IMG_FALSE;
+                       }
+                       OSMemSet(pvCpuVAddr, 0, ui32BlockBytes);
+                       OSUnMapPhysToLin(pvCpuVAddr,
+                                                        ui32BlockBytes,
+                                                        PVRSRV_HAP_KERNEL_ONLY
+                                                        | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+                                                        IMG_NULL);
+
+                       ui32BytesRemaining -= ui32BlockBytes;
+                       ui32CurrentOffset += ui32BlockBytes;
+               }
+       }
+
+       return IMG_TRUE;
+}
+
+static IMG_VOID
+FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
+{
+       BM_MAPPING *pMapping;
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                       "FreeBuf: pBuf=0x%x: DevVAddr=%08X CpuVAddr=0x%x CpuPAddr=%08X",
+                       (IMG_UINTPTR_T)pBuf, pBuf->DevVAddr.uiAddr,
+                       (IMG_UINTPTR_T)pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr));
+
+       
+       pMapping = pBuf->pMapping;
+
+       if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+       {
+               
+               if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+               {
+                       
+                       if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+                       {
+                               
+                               PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
+                       }
+                       else
+                       {
+                               
+                               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+                               pBuf->pMapping = IMG_NULL; 
+                       }
+               }
+       }
+       else
+       {
+               SYS_DATA *psSysData;
+               IMG_BOOL bBufferValid = IMG_TRUE;
+
+               SysAcquireData(&psSysData);
+               if (!List_PVRSRV_DEVICE_NODE_Find(psSysData->psDeviceNodeList, pMapping->psDeviceNode))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Invalid PVRSRV_DEVICE_NODE %p", pMapping->psDeviceNode));
+                       bBufferValid = IMG_FALSE;
+               }
+               else if ((!List_BM_CONTEXT_Find(pMapping->psDeviceNode->sDevMemoryInfo.pBMContext, pMapping->pBMContext)) &&
+                               (pMapping->pBMContext != pMapping->psDeviceNode->sDevMemoryInfo.pBMKernelContext))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Invalid BM_Context %p", pMapping->pBMContext));
+                       bBufferValid = IMG_FALSE;
+               }
+               else if (!List_BM_HEAP_Find(pMapping->pBMContext->psBMHeap, pMapping->pBMHeap))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Invalid BM_Heap %p", pMapping->pBMHeap));
+                       bBufferValid = IMG_FALSE;
+               }
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+               if ((bBufferValid == IMG_TRUE) && pMapping->psDeviceNode->pfnResProfCB)
+               {
+                       pMapping->psDeviceNode->pfnResProfCB((IMG_PVOID)pMapping->psDeviceNode, pMapping->uSize, IMG_FALSE);
+               }
+#endif
+               
+               if(pBuf->hOSMemHandle != pMapping->hOSMemHandle)
+               {
+            
+                       if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+                       {
+                               if (bBufferValid == IMG_TRUE)
+                               {
+                                       OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
+                               }
+                       }
+               }
+               if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+               {
+                       
+            
+                       if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+                       {
+                               
+
+
+                               PVR_ASSERT(pBuf->ui32ExportCount == 0);
+                               if (bBufferValid == IMG_TRUE)
+                               {
+                                       RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+                               }
+                       }
+               }
+               else
+               {
+                       if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+                       {
+                               switch (pMapping->eCpuMemoryOrigin)
+                               {
+                                       case hm_wrapped:
+                                               OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+                                               break;
+                                       case hm_wrapped_virtaddr:
+                                               OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+                                               break;
+                                       case hm_wrapped_scatter:
+                                               OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+                                               break;
+                                       case hm_wrapped_scatter_virtaddr:
+                                               OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+                                               break;
+                                       default:
+                                               break;
+                               }
+                       }
+                       if (bBufferValid == IMG_TRUE && bFromAllocator)
+                       {
+                               DevMemoryFree (pMapping);
+                       }
+
+                       if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+                       {
+                               
+                               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+                               pBuf->pMapping = IMG_NULL; 
+                       }
+               }
+       }
+
+
+       if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
+               
+       }
+}
+
+static PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
+{
+       if(psBMHeap->ui32Attribs
+       &       (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+               |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+       {
+               if (psBMHeap->pImportArena)
+               {
+                       IMG_BOOL bTestDelete = RA_TestDelete(psBMHeap->pImportArena);
+                       if (!bTestDelete)
+                       {
+                               PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext_AnyCb: RA_TestDelete failed"));
+                               return PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP;
+                       }
+               }
+       }
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+BM_DestroyContext(IMG_HANDLE   hBMContext,
+                                 IMG_BOOL              *pbDestroyed)
+{
+       PVRSRV_ERROR eError;
+       BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "BM_DestroyContext"));
+
+       if (pbDestroyed != IMG_NULL)
+       {
+               *pbDestroyed = IMG_FALSE;
+       }
+
+       
+
+       if (pBMContext == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       pBMContext->ui32RefCount--;
+
+       if (pBMContext->ui32RefCount > 0)
+       {
+               
+               return PVRSRV_OK;
+       }
+
+       
+
+
+       eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, &BM_DestroyContext_AnyCb);
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
+#if 0
+               
+               
+               
+               
+               PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Cleaning up with ResManFreeSpecial"));
+               if(ResManFreeSpecial() != PVRSRV_OK)
+               {
+                       PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeSpecial failed %d",eError));
+               }
+               
+#endif
+               return eError;
+       }
+       else
+       {
+               
+               eError = ResManFreeResByPtr(pBMContext->hResItem);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError));
+                       return eError;
+               }
+
+               
+               if (pbDestroyed != IMG_NULL)
+               {
+                       *pbDestroyed = IMG_TRUE;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+
+       
+       if(psBMHeap->ui32Attribs
+       &       (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+               |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+       {
+               if (psBMHeap->pImportArena)
+               {
+                       RA_Delete (psBMHeap->pImportArena);
+               }
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_DestroyContext: backing store type unsupported"));
+               return PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE;
+       }
+
+       
+       psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+       List_BM_HEAP_Remove(psBMHeap);
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+       
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID                pvParam,
+                                                                                         IMG_UINT32    ui32Param)
+{
+       BM_CONTEXT *pBMContext = pvParam;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       PVRSRV_ERROR eError;
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       
+
+       psDeviceNode = pBMContext->psDeviceNode;
+
+       
+
+       eError = List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
+                                                                               &BM_DestroyContextCallBack_AnyVaCb,
+                                                                               psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+       
+
+       if (pBMContext->psMMUContext)
+       {
+               psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+       }
+
+       
+
+       if (pBMContext->pBufferHash)
+       {
+               HASH_Delete(pBMContext->pBufferHash);
+       }
+
+       if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+       {
+               
+               psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL;
+       }
+       else
+       {
+               
+               List_BM_CONTEXT_Remove(pBMContext);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL);
+       
+
+       return PVRSRV_OK;
+}
+
+
+static IMG_HANDLE BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT *pBMContext, va_list va)
+{
+       PRESMAN_CONTEXT hResManContext;
+       hResManContext = va_arg(va, PRESMAN_CONTEXT);
+       if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK)
+       {
+               
+               pBMContext->ui32RefCount++;
+               return pBMContext;
+       }
+       return IMG_NULL;
+}
+
+static IMG_VOID BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       BM_CONTEXT *pBMContext;
+       psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+       pBMContext = va_arg(va, BM_CONTEXT*);
+       switch(psBMHeap->sDevArena.DevMemHeapType)
+       {
+               case DEVICE_MEMORY_HEAP_SHARED:
+               case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+               {
+                       
+                       psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap);
+                       break;
+               }
+       }
+}
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE                    *psDeviceNode,
+                                IMG_DEV_PHYADDR                        *psPDDevPAddr,
+                                PVRSRV_PER_PROCESS_DATA        *psPerProc,
+                                IMG_BOOL                                       *pbCreated)
+{
+       BM_CONTEXT                      *pBMContext;
+       DEVICE_MEMORY_INFO      *psDevMemoryInfo;
+       IMG_BOOL                        bKernelContext;
+       PRESMAN_CONTEXT         hResManContext;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext"));
+
+       if (psPerProc == IMG_NULL)
+       {
+               bKernelContext = IMG_TRUE;
+               hResManContext = psDeviceNode->hResManContext;
+       }
+       else
+       {
+               bKernelContext = IMG_FALSE;
+               hResManContext = psPerProc->hResManContext;
+       }
+
+       if (pbCreated != IMG_NULL)
+       {
+               *pbCreated = IMG_FALSE;
+       }
+
+       
+       psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+       if (bKernelContext == IMG_FALSE)
+       {
+               IMG_HANDLE res = (IMG_HANDLE) List_BM_CONTEXT_Any_va(psDevMemoryInfo->pBMContext,
+                                                                                                                       &BM_CreateContext_IncRefCount_AnyVaCb,
+                                                                                                                       hResManContext);
+               if (res)
+               {
+                       return res;
+               }
+       }
+
+       
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof (struct _BM_CONTEXT_),
+                                        (IMG_PVOID *)&pBMContext, IMG_NULL,
+                                        "Buffer Manager Context") != PVRSRV_OK)
+       {
+               PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: Alloc failed"));
+               return IMG_NULL;
+       }
+       OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT));
+
+       
+       pBMContext->psDeviceNode = psDeviceNode;
+
+       
+       
+       pBMContext->pBufferHash = HASH_Create(32);
+       if (pBMContext->pBufferHash==IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: HASH_Create failed"));
+               goto cleanup;
+       }
+
+       if(psDeviceNode->pfnMMUInitialise(psDeviceNode,
+                                                                               &pBMContext->psMMUContext,
+                                                                               psPDDevPAddr) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: MMUInitialise failed"));
+               goto cleanup;
+       }
+
+       if(bKernelContext)
+       {
+               
+               PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL);
+               psDevMemoryInfo->pBMKernelContext = pBMContext;
+       }
+       else
+       {
+               
+
+
+
+
+               PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
+
+               if (psDevMemoryInfo->pBMKernelContext == IMG_NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: psDevMemoryInfo->pBMKernelContext invalid"));
+                       goto cleanup;
+               }
+
+               PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
+
+               
+
+
+
+               pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap;
+
+               
+
+
+               List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
+                                                               &BM_CreateContext_InsertHeap_ForEachVaCb,
+                                                               psDeviceNode,
+                                                               pBMContext);
+
+               
+               List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext);
+       }
+
+       
+       pBMContext->ui32RefCount++;
+
+       
+       pBMContext->hResItem = ResManRegisterRes(hResManContext,
+                                                                                       RESMAN_TYPE_DEVICEMEM_CONTEXT,
+                                                                                       pBMContext,
+                                                                                       0,
+                                                                                       &BM_DestroyContextCallBack);
+       if (pBMContext->hResItem == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: ResManRegisterRes failed"));
+               goto cleanup;
+       }
+
+       if (pbCreated != IMG_NULL)
+       {
+               *pbCreated = IMG_TRUE;
+       }
+       return (IMG_HANDLE)pBMContext;
+
+cleanup:
+       (IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0);
+
+       return IMG_NULL;
+}
+
+
+static IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+       DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo;
+       psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*);
+       if (psBMHeap->sDevArena.ui32HeapID ==  psDevMemHeapInfo->ui32HeapID)
+       {
+               
+               return psBMHeap;
+       }
+       else
+       {
+               return IMG_NULL;
+       }
+}
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+                          DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
+{
+       BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       BM_HEAP *psBMHeap;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap"));
+
+       if(!pBMContext)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: BM_CONTEXT null"));
+               return IMG_NULL;
+       }
+
+       psDeviceNode = pBMContext->psDeviceNode;
+
+       
+
+
+
+
+       if(pBMContext->ui32RefCount > 0)
+       {
+               psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap,
+                                                                                                &BM_CreateHeap_AnyVaCb,
+                                                                                                psDevMemHeapInfo);
+
+               if (psBMHeap)
+               {
+                       return psBMHeap;
+               }
+       }
+
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof (BM_HEAP),
+                                               (IMG_PVOID *)&psBMHeap, IMG_NULL,
+                                               "Buffer Manager Heap") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed"));
+               return IMG_NULL;
+       }
+
+       OSMemSet (psBMHeap, 0, sizeof (BM_HEAP));
+
+       psBMHeap->sDevArena.ui32HeapID = psDevMemHeapInfo->ui32HeapID;
+       psBMHeap->sDevArena.pszName = psDevMemHeapInfo->pszName;
+       psBMHeap->sDevArena.BaseDevVAddr = psDevMemHeapInfo->sDevVAddrBase;
+       psBMHeap->sDevArena.ui32Size = psDevMemHeapInfo->ui32HeapSize;
+       psBMHeap->sDevArena.DevMemHeapType = psDevMemHeapInfo->DevMemHeapType;
+       psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize;
+       psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
+       psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+
+       
+       psBMHeap->pBMContext = pBMContext;
+
+       psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext,
+                                                                                                       &psBMHeap->sDevArena,
+                                                                                                       &psBMHeap->pVMArena,
+                                                                                                       &psBMHeap->psMMUAttrib);
+       if (!psBMHeap->pMMUHeap)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed"));
+               goto ErrorExit;
+       }
+
+       
+       psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName,
+                                                                               0, 0, IMG_NULL,
+                                                                               MAX(HOST_PAGESIZE(), psBMHeap->sDevArena.ui32DataPageSize),
+                                                                               &BM_ImportMemory,
+                                                                               &BM_FreeMemory,
+                                                                               IMG_NULL,
+                                                                               psBMHeap);
+       if(psBMHeap->pImportArena == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: RA_Create failed"));
+               goto ErrorExit;
+       }
+
+       if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+       {
+               
+
+
+
+               psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena;
+               if(psBMHeap->pLocalDevMemArena == IMG_NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: LocalDevMemArena null"));
+                       goto ErrorExit;
+               }
+       }
+
+       
+       List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
+
+       return (IMG_HANDLE)psBMHeap;
+
+       
+ErrorExit:
+
+       
+       if (psBMHeap->pMMUHeap != IMG_NULL)
+       {
+               psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+               psDeviceNode->pfnMMUFinalise (pBMContext->psMMUContext);
+       }
+
+       
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+       
+
+       return IMG_NULL;
+}
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
+{
+       BM_HEAP* psBMHeap = (BM_HEAP*)hDevMemHeap;
+       PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyHeap"));
+
+       if(psBMHeap)
+       {
+               
+               if(psBMHeap->ui32Attribs
+               &       (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+                       |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+               {
+                       if (psBMHeap->pImportArena)
+                       {
+                               RA_Delete (psBMHeap->pImportArena);
+                       }
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "BM_DestroyHeap: backing store type unsupported"));
+                       return;
+               }
+
+               
+               psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+
+               
+               List_BM_HEAP_Remove(psBMHeap);
+               
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+               
+       }
+       else
+       {
+               PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyHeap: invalid heap handle"));
+       }
+}
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+       PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+       return IMG_TRUE;
+}
+
+IMG_BOOL
+BM_Alloc (  IMG_HANDLE                 hDevMemHeap,
+                       IMG_DEV_VIRTADDR        *psDevVAddr,
+                       IMG_SIZE_T                      uSize,
+                       IMG_UINT32                      *pui32Flags,
+                       IMG_UINT32                      uDevVAddrAlignment,
+                       BM_HANDLE                       *phBuf)
+{
+       BM_BUF *pBuf;
+       BM_CONTEXT *pBMContext;
+       BM_HEAP *psBMHeap;
+       SYS_DATA *psSysData;
+       IMG_UINT32 uFlags;
+
+       if (pui32Flags == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: invalid parameter"));
+               PVR_DBG_BREAK;
+               return IMG_FALSE;
+       }
+
+       uFlags = *pui32Flags;
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                 "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)",
+                       uSize, uFlags, uDevVAddrAlignment));
+
+       SysAcquireData(&psSysData);
+
+       psBMHeap = (BM_HEAP*)hDevMemHeap;
+       pBMContext = psBMHeap->pBMContext;
+
+       if(uDevVAddrAlignment == 0)
+       {
+               uDevVAddrAlignment = 1;
+       }
+
+       
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                  sizeof (BM_BUF),
+                                  (IMG_PVOID *)&pBuf, IMG_NULL,
+                                  "Buffer Manager buffer") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED"));
+               return IMG_FALSE;
+       }
+       OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+       
+       if (AllocMemory(pBMContext,
+                                       psBMHeap,
+                                       psDevVAddr,
+                                       uSize,
+                                       uFlags,
+                                       uDevVAddrAlignment,
+                                       pBuf) != IMG_TRUE)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+               
+               PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
+               return IMG_FALSE;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                 "BM_Alloc (uSize=0x%x, uFlags=0x%x)",
+                 uSize, uFlags));
+
+       
+       pBuf->ui32RefCount = 1;
+       *phBuf = (BM_HANDLE)pBuf;
+       *pui32Flags = uFlags | psBMHeap->ui32Attribs;
+
+       
+       if(uFlags & PVRSRV_HAP_CACHETYPE_MASK)
+       {
+               *pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+               *pui32Flags |= (uFlags & PVRSRV_HAP_CACHETYPE_MASK);
+       }
+
+       return IMG_TRUE;
+}
+
+
+
+#if defined(PVR_LMA)
+static IMG_BOOL
+ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T ui32PageSize)
+{
+       IMG_UINT32 i;
+
+       for (i = 0; i < ui32PageCount; i++)
+       {
+               IMG_SYS_PHYADDR sStartSysPAddr = psSysPAddr[i];
+               IMG_SYS_PHYADDR sEndSysPAddr;
+
+               if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+               {
+                       return IMG_FALSE;
+               }
+
+               sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32PageSize;
+
+               if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+               {
+                       return IMG_FALSE;
+               }
+       }
+
+       return IMG_TRUE;
+}
+
+static IMG_BOOL
+ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T ui32Range)
+{
+       IMG_SYS_PHYADDR sEndSysPAddr;
+
+       if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+       {
+               return IMG_FALSE;
+       }
+
+       sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32Range;
+
+       if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+       {
+               return IMG_FALSE;
+       }
+
+       return IMG_TRUE;
+}
+
+#define        WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) HOST_PAGEALIGN((ui32ByteSize) + (ui32PageOffset))
+
+#define        WRAP_PAGE_COUNT(ui32ByteSize, ui32PageOffset, ui32HostPageSize) (WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) / (ui32HostPageSize))
+
+#endif
+
+
+IMG_BOOL
+BM_Wrap (      IMG_HANDLE hDevMemHeap,
+                       IMG_SIZE_T ui32Size,
+                       IMG_SIZE_T ui32Offset,
+                       IMG_BOOL bPhysContig,
+                       IMG_SYS_PHYADDR *psSysAddr,
+                       IMG_VOID *pvCPUVAddr,
+                       IMG_UINT32 *pui32Flags,
+                       BM_HANDLE *phBuf)
+{
+       BM_BUF *pBuf;
+       BM_CONTEXT *psBMContext;
+       BM_HEAP *psBMHeap;
+       SYS_DATA *psSysData;
+       IMG_SYS_PHYADDR sHashAddress;
+       IMG_UINT32 uFlags;
+
+       psBMHeap = (BM_HEAP*)hDevMemHeap;
+       psBMContext = psBMHeap->pBMContext;
+
+       uFlags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK);
+
+       if ((pui32Flags != IMG_NULL) && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0))
+       {
+               uFlags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+               uFlags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                 "BM_Wrap (uSize=0x%x, uOffset=0x%x, bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)",
+                       ui32Size, ui32Offset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));
+
+       SysAcquireData(&psSysData);
+
+#if defined(PVR_LMA)
+       if (bPhysContig)
+       {
+               if (!ValidSysPAddrRangeForDev(psBMContext->psDeviceNode, *psSysAddr, WRAP_MAPPING_SIZE(ui32Size, ui32Offset)))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: System address range invalid for device"));
+                       return IMG_FALSE;
+               }
+       }
+       else
+       {
+               IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+
+               if (!ValidSysPAddrArrayForDev(psBMContext->psDeviceNode, psSysAddr, WRAP_PAGE_COUNT(ui32Size, ui32Offset, ui32HostPageSize), ui32HostPageSize))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: Array of system addresses invalid for device"));
+                       return IMG_FALSE;
+               }
+       }
+#endif
+       
+       sHashAddress = psSysAddr[0];
+
+       
+       sHashAddress.uiAddr += ui32Offset;
+
+       
+       pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, sHashAddress.uiAddr);
+
+       if(pBuf)
+       {
+               IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset);
+
+               
+               if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped ||
+                                                                                                               pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr))
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,
+                                       "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
+                                       ui32Size, ui32Offset, sHashAddress.uiAddr));
+
+                       pBuf->ui32RefCount++;
+                       *phBuf = (BM_HANDLE)pBuf;
+                       if(pui32Flags)
+                               *pui32Flags = uFlags;
+
+                       return IMG_TRUE;
+               }
+       }
+
+       
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof (BM_BUF),
+                                               (IMG_PVOID *)&pBuf, IMG_NULL,
+                                               "Buffer Manager buffer") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED"));
+               return IMG_FALSE;
+       }
+       OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+       
+       if (WrapMemory (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+               
+               return IMG_FALSE;
+       }
+
+       
+       if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+       {
+               
+               PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr);
+
+               if (!HASH_Insert (psBMContext->pBufferHash, sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf))
+               {
+                       FreeBuf (pBuf, uFlags, IMG_TRUE);
+                       PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"));
+                       return IMG_FALSE;
+               }
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                       "BM_Wrap (uSize=0x%x, uFlags=0x%x, devVAddr=%08X)",
+                       ui32Size, uFlags, pBuf->DevVAddr.uiAddr));
+
+       
+       pBuf->ui32RefCount = 1;
+       *phBuf = (BM_HANDLE)pBuf;
+       if(pui32Flags)
+       {
+               
+               *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS;
+       }
+
+       return IMG_TRUE;
+}
+
+IMG_VOID
+BM_Export (BM_HANDLE hBuf)
+{
+       BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+       pBuf->ui32ExportCount++;
+}
+
+IMG_VOID
+BM_FreeExport(BM_HANDLE hBuf,
+               IMG_UINT32 ui32Flags)
+{
+       BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+       pBuf->ui32ExportCount--;
+       FreeBuf (pBuf, ui32Flags, IMG_FALSE);
+}
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+               IMG_UINT32 ui32Flags)
+{
+       BM_BUF *pBuf = (BM_BUF *)hBuf;
+       SYS_DATA *psSysData;
+       IMG_SYS_PHYADDR sHashAddr;
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "BM_Free (h=0x%x)", (IMG_UINTPTR_T)hBuf));
+       PVR_ASSERT (pBuf!=IMG_NULL);
+
+       if (pBuf == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter"));
+               return;
+       }
+
+       SysAcquireData(&psSysData);
+
+       pBuf->ui32RefCount--;
+
+       if(pBuf->ui32RefCount == 0)
+       {
+               if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+               {
+                       sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+
+                       HASH_Remove (pBuf->pMapping->pBMHeap->pBMContext->pBufferHash,  (IMG_UINTPTR_T)sHashAddr.uiAddr);
+               }
+               FreeBuf (pBuf, ui32Flags, IMG_TRUE);
+       }
+}
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf)
+{
+       BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+       PVR_ASSERT (pBuf != IMG_NULL);
+       if (pBuf == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_HandleToCpuVaddr: invalid parameter"));
+               return IMG_NULL;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                               "BM_HandleToCpuVaddr(h=0x%x)=0x%x",
+                               (IMG_UINTPTR_T)hBuf, (IMG_UINTPTR_T)pBuf->CpuVAddr));
+       return pBuf->CpuVAddr;
+}
+
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf)
+{
+       BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+       PVR_ASSERT (pBuf != IMG_NULL);
+       if (pBuf == IMG_NULL)
+       {
+               IMG_DEV_VIRTADDR        DevVAddr = {0};
+               PVR_DPF((PVR_DBG_ERROR, "BM_HandleToDevVaddr: invalid parameter"));
+               return DevVAddr;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=0x%x)=%08X", (IMG_UINTPTR_T)hBuf, pBuf->DevVAddr.uiAddr));
+       return pBuf->DevVAddr;
+}
+
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf)
+{
+       BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+       PVR_ASSERT (pBuf != IMG_NULL);
+
+       if (pBuf == IMG_NULL)
+       {
+               IMG_SYS_PHYADDR PhysAddr = {0};
+               PVR_DPF((PVR_DBG_ERROR, "BM_HandleToSysPaddr: invalid parameter"));
+               return PhysAddr;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=0x%x)=%08X", (IMG_UINTPTR_T)hBuf, pBuf->CpuPAddr.uiAddr));
+       return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr);
+}
+
+IMG_HANDLE
+BM_HandleToOSMemHandle(BM_HANDLE hBuf)
+{
+       BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+       PVR_ASSERT (pBuf != IMG_NULL);
+
+       if (pBuf == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_HandleToOSMemHandle: invalid parameter"));
+               return IMG_NULL;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                               "BM_HandleToOSMemHandle(h=0x%x)=0x%x",
+                               (IMG_UINTPTR_T)hBuf, (IMG_UINTPTR_T)pBuf->hOSMemHandle));
+       return pBuf->hOSMemHandle;
+}
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+                               BM_MAPPING *pMapping,
+                               IMG_SIZE_T *pActualSize,
+                               IMG_UINT32 uFlags,
+                               IMG_UINT32 dev_vaddr_alignment,
+                               IMG_DEV_VIRTADDR *pDevVAddr)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+       IMG_UINT32 ui32PDumpSize = pMapping->uSize;
+#endif
+
+       psDeviceNode = pBMContext->psDeviceNode;
+
+       if(uFlags & PVRSRV_MEM_INTERLEAVED)
+       {
+               
+               pMapping->uSize *= 2;
+       }
+
+#ifdef PDUMP
+       if(uFlags & PVRSRV_MEM_DUMMY)
+       {
+               
+               ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+       }
+#endif
+
+       
+       if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap,
+                                                                       pMapping->uSize,
+                                                                       pActualSize,
+                                                                       0,
+                                                                       dev_vaddr_alignment,
+                                                                       &(pMapping->DevVAddr)))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc"));
+               return IMG_FALSE;
+       }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+       EnableHostAccess(pBMContext->psMMUContext);
+#endif
+
+#if defined(PDUMP)
+       
+       PDUMPMALLOCPAGES(&psDeviceNode->sDevId,
+                                        pMapping->DevVAddr.uiAddr,
+                                        pMapping->CpuVAddr,
+                                        pMapping->hOSMemHandle,
+                                        ui32PDumpSize,
+                                        pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+                                        psDeviceNode->pfnMMUIsHeapShared(pMapping->pBMHeap->pMMUHeap),
+#else
+                                        IMG_FALSE,
+#endif
+                                        (IMG_HANDLE)pMapping);
+#endif
+
+       switch (pMapping->eCpuMemoryOrigin)
+       {
+               case hm_wrapped:
+               case hm_wrapped_virtaddr:
+               case hm_contiguous:
+               {
+                       psDeviceNode->pfnMMUMapPages (  pMapping->pBMHeap->pMMUHeap,
+                                                       pMapping->DevVAddr,
+                                                       SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+                                                       pMapping->uSize,
+                                                       uFlags,
+                                                       (IMG_HANDLE)pMapping);
+
+                       *pDevVAddr = pMapping->DevVAddr;
+                       break;
+               }
+               case hm_env:
+               {
+                       psDeviceNode->pfnMMUMapShadow ( pMapping->pBMHeap->pMMUHeap,
+                                                       pMapping->DevVAddr,
+                                                       pMapping->uSize,
+                                                       pMapping->CpuVAddr,
+                                                       pMapping->hOSMemHandle,
+                                                       pDevVAddr,
+                                                       uFlags,
+                                                       (IMG_HANDLE)pMapping);
+                       break;
+               }
+               case hm_wrapped_scatter:
+               case hm_wrapped_scatter_virtaddr:
+               {
+                       psDeviceNode->pfnMMUMapScatter (pMapping->pBMHeap->pMMUHeap,
+                                                       pMapping->DevVAddr,
+                                                       pMapping->psSysAddr,
+                                                       pMapping->uSize,
+                                                       uFlags,
+                                                       (IMG_HANDLE)pMapping);
+
+                       *pDevVAddr = pMapping->DevVAddr;
+                       break;
+               }
+               default:
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "Illegal value %d for pMapping->eCpuMemoryOrigin",
+                               pMapping->eCpuMemoryOrigin));
+                       return IMG_FALSE;
+       }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+       DisableHostAccess(pBMContext->psMMUContext);
+#endif
+
+       return IMG_TRUE;
+}
+
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+       IMG_UINT32 ui32PSize;
+#endif
+
+#ifdef PDUMP
+       
+       if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+       {
+               
+               ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+       }
+       else
+       {
+               ui32PSize = pMapping->uSize;
+       }
+
+       PDUMPFREEPAGES(pMapping->pBMHeap,
+                    pMapping->DevVAddr,
+                    ui32PSize,
+                    pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+                    (IMG_HANDLE)pMapping,
+                    (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE);
+#endif
+
+       psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+       psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize));
+}
+
+static IMG_BOOL
+BM_ImportMemory (IMG_VOID *pH,
+                         IMG_SIZE_T uRequestSize,
+                         IMG_SIZE_T *pActualSize,
+                         BM_MAPPING **ppsMapping,
+                         IMG_UINT32 uFlags,
+                         IMG_UINTPTR_T *pBase)
+{
+       BM_MAPPING *pMapping;
+       BM_HEAP *pBMHeap = pH;
+       BM_CONTEXT *pBMContext = pBMHeap->pBMContext;
+       IMG_BOOL bResult;
+       IMG_SIZE_T uSize;
+       IMG_SIZE_T uPSize;
+       IMG_UINT32 uDevVAddrAlignment = 0;
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "BM_ImportMemory (pBMContext=0x%x, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
+                         (IMG_UINTPTR_T)pBMContext, uRequestSize, uFlags, uDevVAddrAlignment));
+
+       PVR_ASSERT (ppsMapping != IMG_NULL);
+       PVR_ASSERT (pBMContext != IMG_NULL);
+
+       if (ppsMapping == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: invalid parameter"));
+               goto fail_exit;
+       }
+
+       uSize = HOST_PAGEALIGN (uRequestSize);
+       PVR_ASSERT (uSize >= uRequestSize);
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof (BM_MAPPING),
+                                               (IMG_PVOID *)&pMapping, IMG_NULL,
+                                               "Buffer Manager Mapping") != PVRSRV_OK)
+       {
+               PVR_DPF ((PVR_DBG_ERROR, "BM_ImportMemory: failed BM_MAPPING alloc"));
+               goto fail_exit;
+       }
+
+       pMapping->hOSMemHandle = 0;
+       pMapping->CpuVAddr = 0;
+       pMapping->DevVAddr.uiAddr = 0;
+       pMapping->CpuPAddr.uiAddr = 0;
+       pMapping->uSize = uSize;
+       pMapping->pBMHeap = pBMHeap;
+       pMapping->ui32Flags = uFlags;
+       pMapping->psDeviceNode = pBMContext->psDeviceNode;
+       pMapping->pBMContext = pBMContext;
+       
+       if (pActualSize)
+       {
+               *pActualSize = uSize;
+       }
+
+       
+       if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+       {
+               uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+       }
+       else
+       {
+               uPSize = pMapping->uSize;
+       }
+
+       
+
+       if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+       {
+               IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+               
+               if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+               {
+                       ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+                       ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+               }
+
+               
+               if (OSAllocPages(ui32Attribs,
+                                                uPSize,
+                                                pBMHeap->sDevArena.ui32DataPageSize,
+                                                (IMG_VOID **)&pMapping->CpuVAddr,
+                                                &pMapping->hOSMemHandle) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "BM_ImportMemory: OSAllocPages(0x%x) failed",
+                                       uPSize));
+                       goto fail_mapping_alloc;
+               }
+
+               
+               pMapping->eCpuMemoryOrigin = hm_env;
+       }
+       else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+       {
+               IMG_SYS_PHYADDR sSysPAddr;
+               IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+               
+               PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
+
+               
+               if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+               {
+                       ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+                       ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+               }
+
+               if (!RA_Alloc (pBMHeap->pLocalDevMemArena,
+                                          uPSize,
+                                          IMG_NULL,
+                                          IMG_NULL,
+                                          0,
+                                          pBMHeap->sDevArena.ui32DataPageSize,
+                                          0,
+                                          (IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize));
+                       goto fail_mapping_alloc;
+               }
+
+               
+               pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+               if(OSReservePhys(pMapping->CpuPAddr,
+                                                uPSize,
+                                                ui32Attribs,
+                                                &pMapping->CpuVAddr,
+                                                &pMapping->hOSMemHandle) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: OSReservePhys failed"));
+                       goto fail_dev_mem_alloc;
+               }
+
+               
+               pMapping->eCpuMemoryOrigin = hm_contiguous;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: Invalid backing store type"));
+               goto fail_mapping_alloc;
+       }
+
+       
+       bResult = DevMemoryAlloc (pBMContext,
+                                                               pMapping,
+                                                               IMG_NULL,
+                                                               uFlags,
+                                                               uDevVAddrAlignment,
+                                                               &pMapping->DevVAddr);
+       if (!bResult)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
+                               pMapping->uSize));
+               goto fail_dev_mem_alloc;
+       }
+
+       
+       
+       PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+
+       *pBase = pMapping->DevVAddr.uiAddr;
+       *ppsMapping = pMapping;
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE"));
+       return IMG_TRUE;
+
+fail_dev_mem_alloc:
+       if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+       {
+               
+               if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED)
+               {
+                       pMapping->uSize /= 2;
+               }
+
+               if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+               {
+                       uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+               }
+               else
+               {
+                       uPSize = pMapping->uSize;
+               }
+
+               if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+               {
+                       OSFreePages(pBMHeap->ui32Attribs,
+                                                 uPSize,
+                                                 (IMG_VOID *)pMapping->CpuVAddr,
+                                                 pMapping->hOSMemHandle);
+               }
+               else
+               {
+                       IMG_SYS_PHYADDR sSysPAddr;
+
+                       if(pMapping->CpuVAddr)
+                       {
+                               OSUnReservePhys(pMapping->CpuVAddr,
+                                                               uPSize,
+                                                               pBMHeap->ui32Attribs,
+                                                               pMapping->hOSMemHandle);
+                       }
+                       sSysPAddr = SysCpuPAddrToSysPAddr(pMapping->CpuPAddr);
+                       RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+               }
+       }
+fail_mapping_alloc:
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+       
+fail_exit:
+       return IMG_FALSE;
+}
+
+
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
+{
+       BM_HEAP *pBMHeap = h;
+       IMG_SIZE_T uPSize;
+
+       PVR_UNREFERENCED_PARAMETER (_base);
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "BM_FreeMemory (h=0x%x, base=0x%x, psMapping=0x%x)",
+                         (IMG_UINTPTR_T)h, _base, (IMG_UINTPTR_T)psMapping));
+
+       PVR_ASSERT (psMapping != IMG_NULL);
+
+       if (psMapping == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter"));
+               return;
+       }
+
+       DevMemoryFree (psMapping);
+
+       
+       if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0)
+       {
+               psMapping->uSize /= 2;
+       }
+
+       if(psMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+       {
+               uPSize = psMapping->pBMHeap->sDevArena.ui32DataPageSize;
+       }
+       else
+       {
+               uPSize = psMapping->uSize;
+       }
+
+       if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+       {
+               OSFreePages(pBMHeap->ui32Attribs,
+                                               uPSize,
+                                               (IMG_VOID *) psMapping->CpuVAddr,
+                                               psMapping->hOSMemHandle);
+       }
+       else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+       {
+               IMG_SYS_PHYADDR sSysPAddr;
+
+               OSUnReservePhys(psMapping->CpuVAddr, uPSize, pBMHeap->ui32Attribs, psMapping->hOSMemHandle);
+
+               sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr);
+
+               RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: Invalid backing store type"));
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL);
+       
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "..BM_FreeMemory (h=0x%x, base=0x%x)",
+                       (IMG_UINTPTR_T)h, _base));
+}
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                               IMG_DEV_VIRTADDR sDevVPageAddr,
+                                                               IMG_DEV_PHYADDR *psDevPAddr)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
+
+       PVR_ASSERT (psMemInfo && psDevPAddr)
+
+       
+       PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+       psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+       *psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap,
+                                                                                               sDevVPageAddr);
+}
+
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
+{
+       BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap;
+
+       PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext"));
+
+       return pBMHeap->pBMContext->psMMUContext;
+}
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
+{
+       BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext;
+
+       PVR_DPF ((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext"));
+
+       return pBMContext->psMMUContext;
+}
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
+{
+       PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
+
+       return (IMG_HANDLE)((BM_HEAP*)hDevMemHeap)->pMMUHeap;
+}
+
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
+{
+       PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
+
+       return ((BM_CONTEXT*)hDevMemContext)->psDeviceNode;
+}
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+       PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
+
+       return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/deviceclass.c b/drivers/staging/mrst/pvr/services4/srvkm/common/deviceclass.c
new file mode 100644 (file)
index 0000000..e43e8f8
--- /dev/null
@@ -0,0 +1,2025 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "kernelbuffer.h"
+#include "kerneldisplay.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "deviceid.h"
+
+#include "lists.h"
+#include "pvr_trace_cmd.h"
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#if defined(SUPPORT_MISR_IN_THREAD)
+void OSVSyncMISR(IMG_HANDLE, IMG_BOOL);
+#endif
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE  hCmdCookie,
+                                                                                  IMG_BOOL             bScheduleMISR);
+#endif
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef struct PVRSRV_DC_BUFFER_TAG
+{
+       
+       PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+       struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+       struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+} PVRSRV_DC_BUFFER;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_TAG
+{
+       IMG_HANDLE                                                      hExtSwapChain;
+       IMG_UINT32                                                      ui32SwapChainID;
+       IMG_UINT32                                                      ui32RefCount;
+       IMG_UINT32                                                      ui32Flags;
+       PVRSRV_QUEUE_INFO                                       *psQueue;
+       PVRSRV_DC_BUFFER                                        asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+       IMG_UINT32                                                      ui32BufferCount;
+       PVRSRV_DC_BUFFER                                        *psLastFlipBuffer;
+       IMG_UINT32                                                      ui32MinSwapInterval;
+       IMG_UINT32                                                      ui32MaxSwapInterval;
+       struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+       struct PVRSRV_DC_SWAPCHAIN_TAG          *psNext;
+} PVRSRV_DC_SWAPCHAIN;
+
+
+typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
+{
+       struct PVRSRV_DC_SWAPCHAIN_TAG          *psSwapChain;
+       IMG_HANDLE                                                      hResItem;       
+} PVRSRV_DC_SWAPCHAIN_REF;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
+{
+       IMG_UINT32                                                      ui32RefCount;
+       IMG_UINT32                                                      ui32DeviceID;
+       IMG_HANDLE                                                      hExtDevice;
+       PPVRSRV_DC_SRV2DISP_KMJTABLE            psFuncTable;
+       IMG_HANDLE                                                      hDevMemContext;
+       PVRSRV_DC_BUFFER                                        sSystemBuffer;
+       struct PVRSRV_DC_SWAPCHAIN_TAG          *psDCSwapChainShared;
+} PVRSRV_DISPLAYCLASS_INFO;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
+{
+       PVRSRV_DISPLAYCLASS_INFO                        *psDCInfo;
+       PRESMAN_ITEM                                            hResItem;
+} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+typedef struct PVRSRV_BC_BUFFER_TAG
+{
+       
+       PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+       struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
+} PVRSRV_BC_BUFFER;
+
+
+typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
+{
+       IMG_UINT32                                                      ui32RefCount;
+       IMG_UINT32                                                      ui32DeviceID;
+       IMG_HANDLE                                                      hExtDevice;
+       PPVRSRV_BC_SRV2BUFFER_KMJTABLE          psFuncTable;
+       IMG_HANDLE                                                      hDevMemContext;
+       
+       IMG_UINT32                                                      ui32BufferCount;
+       PVRSRV_BC_BUFFER                                        *psBuffer;
+
+} PVRSRV_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
+{
+       PVRSRV_BUFFERCLASS_INFO                         *psBCInfo;
+       IMG_HANDLE                                                      hResItem;
+} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+
+
+static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
+{
+       PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+       psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+       return psDCPerContextInfo->psDCInfo;
+}
+
+
+static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
+{
+       PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+       psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+       return psBCPerContextInfo->psBCInfo;
+}
+
+static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+       IMG_UINT *pui32DevCount;
+       IMG_UINT32 **ppui32DevID;
+       PVRSRV_DEVICE_CLASS peDeviceClass;
+
+       pui32DevCount = va_arg(va, IMG_UINT*);
+       ppui32DevID = va_arg(va, IMG_UINT32**);
+       peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+
+       if      ((psDeviceNode->sDevId.eDeviceClass == peDeviceClass)
+       &&      (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT))
+       {
+               (*pui32DevCount)++;
+               if(*ppui32DevID)
+               {
+                       *(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex;
+               }
+       }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
+                                                                 IMG_UINT32 *pui32DevCount,
+                                                                 IMG_UINT32 *pui32DevID )
+{
+       
+       IMG_UINT                        ui32DevCount = 0;
+       SYS_DATA                        *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       
+       List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+                                                                               &PVRSRVEnumerateDCKM_ForEachVaCb,
+                                                                               &ui32DevCount,
+                                                                               &pui32DevID,
+                                                                               DeviceClass);
+
+       if(pui32DevCount)
+       {
+               *pui32DevCount = ui32DevCount;
+       }
+       else if(pui32DevID == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters"));
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+                                                                          IMG_UINT32 *pui32DeviceID)
+{
+       PVRSRV_DISPLAYCLASS_INFO        *psDCInfo = IMG_NULL;
+       PVRSRV_DEVICE_NODE                      *psDeviceNode;
+       SYS_DATA                                        *psSysData;
+
+       
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+       SysAcquireData(&psSysData);
+
+       
+
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(*psDCInfo),
+                                        (IMG_VOID **)&psDCInfo, IMG_NULL,
+                                        "Display Class Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+                                        (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
+                                        "Function table for SRVKM->DISPLAY") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc"));
+               goto ErrorExit;
+       }
+       OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
+
+       
+       *psDCInfo->psFuncTable = *psFuncTable;
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_DEVICE_NODE),
+                                        (IMG_VOID **)&psDeviceNode, IMG_NULL,
+                                        "Device Node") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc"));
+               goto ErrorExit;
+       }
+       OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+       psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo;
+       psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
+       psDeviceNode->ui32RefCount = 1;
+       psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+       psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
+       psDeviceNode->psSysData = psSysData;
+
+       
+       if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+               goto ErrorExit;
+       }
+       psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+       if (pui32DeviceID)
+       {
+               *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+       }
+
+       
+       SysRegisterExternalDevice(psDeviceNode);
+
+       
+       List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       if(psDCInfo->psFuncTable)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+               psDCInfo->psFuncTable = IMG_NULL;
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+       
+
+       return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+       SYS_DATA                                        *psSysData;
+       PVRSRV_DEVICE_NODE                      *psDeviceNode;
+       PVRSRV_DISPLAYCLASS_INFO        *psDCInfo;
+
+       SysAcquireData(&psSysData);
+
+       
+       psDeviceNode = (PVRSRV_DEVICE_NODE*)
+               List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                          &MatchDeviceKM_AnyVaCb,
+                                                                          ui32DevIndex,
+                                                                          IMG_FALSE,
+                                                                          PVRSRV_DEVICE_CLASS_DISPLAY);
+       if (!psDeviceNode)
+       {
+               
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
+               return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+       }
+
+       
+       psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+       
+
+
+       if(psDCInfo->ui32RefCount == 0)
+       {
+               
+
+               List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+               
+               SysRemoveExternalDevice(psDeviceNode);
+
+               
+
+
+               PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+               (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+               (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+               psDCInfo->psFuncTable = IMG_NULL;
+               (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+               
+               (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+               
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount));
+               return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
+                                                                          IMG_UINT32   *pui32DeviceID)
+{
+       PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL;
+       PVRSRV_DEVICE_NODE              *psDeviceNode;
+       SYS_DATA                                *psSysData;
+       
+
+
+
+
+
+
+
+
+
+
+
+
+
+       SysAcquireData(&psSysData);
+
+       
+
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(*psBCInfo),
+                                        (IMG_VOID **)&psBCInfo, IMG_NULL,
+                                        "Buffer Class Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+                                        (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
+                                        "Function table for SRVKM->BUFFER") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc"));
+               goto ErrorExit;
+       }
+       OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
+
+       
+       *psBCInfo->psFuncTable = *psFuncTable;
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_DEVICE_NODE),
+                                        (IMG_VOID **)&psDeviceNode, IMG_NULL,
+                                        "Device Node") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc"));
+               goto ErrorExit;
+       }
+       OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+       psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo;
+       psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
+       psDeviceNode->ui32RefCount = 1;
+       psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+       psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
+       psDeviceNode->psSysData = psSysData;
+
+       
+       if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+               goto ErrorExit;
+       }
+       psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+       if (pui32DeviceID)
+       {
+               *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+       }
+
+       
+       List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       if(psBCInfo->psFuncTable)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+               psBCInfo->psFuncTable = IMG_NULL;
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+       
+
+       return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+
+static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+       SYS_DATA                                        *psSysData;
+       PVRSRV_DEVICE_NODE                      *psDevNode;
+       PVRSRV_BUFFERCLASS_INFO         *psBCInfo;
+
+       SysAcquireData(&psSysData);
+
+       
+       psDevNode = (PVRSRV_DEVICE_NODE*)
+               List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                          &MatchDeviceKM_AnyVaCb,
+                                                                          ui32DevIndex,
+                                                                          IMG_FALSE,
+                                                                          PVRSRV_DEVICE_CLASS_BUFFER);
+
+       if (!psDevNode)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex));
+               return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+       }
+
+       
+       
+       psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
+
+       
+
+
+       if(psBCInfo->ui32RefCount == 0)
+       {
+               
+
+               List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
+
+               
+
+
+               (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+               
+               
+               (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+               psBCInfo->psFuncTable = IMG_NULL;
+               (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+               
+               (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
+               
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount));
+               return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM,
+                                                                       IMG_BOOL        bResManCallback)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+       PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+       psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+       
+       eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem);
+
+       return eError;
+}
+
+
+static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID            pvParam,
+                                                                                 IMG_UINT32    ui32Param)
+{
+       PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam;
+       psDCInfo = psDCPerContextInfo->psDCInfo;
+
+       psDCInfo->ui32RefCount--;
+       if(psDCInfo->ui32RefCount == 0)
+       {
+               
+               psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
+
+               if (--psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+               {
+                       PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+               }
+
+               psDCInfo->hDevMemContext = IMG_NULL;
+               psDCInfo->hExtDevice = IMG_NULL;
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
+       
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA     *psPerProc,
+                                                                  IMG_UINT32                           ui32DeviceID,
+                                                                  IMG_HANDLE                           hDevCookie,
+                                                                  IMG_HANDLE                           *phDeviceKM)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       SYS_DATA                        *psSysData;
+       PVRSRV_ERROR eError;
+
+       if(!phDeviceKM || !hDevCookie)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       SysAcquireData(&psSysData);
+
+       
+       psDeviceNode = (PVRSRV_DEVICE_NODE*)
+                       List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                  &MatchDeviceKM_AnyVaCb,
+                                                                                  ui32DeviceID,
+                                                                                  IMG_FALSE,
+                                                                                  PVRSRV_DEVICE_CLASS_DISPLAY);
+       if (!psDeviceNode)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID));
+               return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+       }
+       psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+       
+
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(*psDCPerContextInfo),
+                                 (IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
+                                 "Display Class per Context Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
+
+       if(psDCInfo->ui32RefCount++ == 0)
+       {
+
+               psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+               
+               psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+               
+               eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+                                                                       (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
+                                                                       &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc"));
+                       psDCInfo->ui32RefCount--;
+                       return eError;
+               }
+
+               
+               eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
+                                                               &psDCInfo->hExtDevice,
+                                                               (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
+                       psDCInfo->ui32RefCount--;
+                       PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+                       return eError;
+               }
+
+               psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+       }
+
+       psDCPerContextInfo->psDCInfo = psDCInfo;
+       psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                        RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+                                                                                                        psDCPerContextInfo,
+                                                                                                        0,
+                                                                                                        &CloseDCDeviceCallBack);
+
+       
+       *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
+                                                                       IMG_UINT32 *pui32Count,
+                                                                       DISPLAY_FORMAT *psFormat)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+       if(!hDeviceKM || !pui32Count || !psFormat)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+       
+       return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
+                                                                DISPLAY_FORMAT *psFormat,
+                                                                IMG_UINT32 *pui32Count,
+                                                                DISPLAY_DIMS *psDim)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+       if(!hDeviceKM || !pui32Count || !psFormat)      
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+       
+       return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
+                                                                               IMG_HANDLE *phBuffer)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       IMG_HANDLE hExtBuffer;
+
+       if(!hDeviceKM || !phBuffer)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+       
+       eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver"));
+               return eError;
+       }
+
+       
+       psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+       psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+       psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+       psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
+
+       psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
+
+       
+       *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
+                                                               DISPLAY_INFO *psDisplayInfo)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_ERROR eError;
+
+       if(!hDeviceKM || !psDisplayInfo)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+       
+       eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+       {
+               psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+
+       if(!hSwapChainRef)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psSwapChainRef = hSwapChainRef;
+
+       eError = ResManFreeResByPtr(psSwapChainRef->hResItem);
+
+       return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
+{
+       PVRSRV_ERROR                            eError;
+       PVRSRV_DISPLAYCLASS_INFO        *psDCInfo = psSwapChain->psDCInfo;
+       IMG_UINT32 i;
+
+
+       
+       if( psDCInfo->psDCSwapChainShared )
+       {
+               if( psDCInfo->psDCSwapChainShared == psSwapChain )
+               {
+                       psDCInfo->psDCSwapChainShared = psSwapChain->psNext;
+               }
+               else 
+               {
+                       PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+                       psCurrentSwapChain = psDCInfo->psDCSwapChainShared;             
+                       while( psCurrentSwapChain->psNext )
+                       {
+                               if( psCurrentSwapChain->psNext != psSwapChain ) 
+                               {
+                                       psCurrentSwapChain = psCurrentSwapChain->psNext;
+                                       continue;
+                               }
+                               psCurrentSwapChain->psNext = psSwapChain->psNext;
+                               break;                          
+                       }
+               }
+       }
+
+       
+       PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
+
+       
+       eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
+                                                                                                                       psSwapChain->hExtSwapChain);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain"));
+               return eError;
+       }
+
+       
+       for(i=0; i<psSwapChain->ui32BufferCount; i++)
+       {
+               if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+               {
+                       if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+                       {
+                               PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+                       }
+               }
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+       
+
+       return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+       PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       if(--psSwapChainRef->psSwapChain->ui32RefCount == 0) 
+       {
+               eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL);
+       return eError;
+}
+
+static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo,
+                                                                                                                IMG_UINT32 ui32SwapChainID)
+{
+       PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+
+       for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared; 
+               psCurrentSwapChain; 
+               psCurrentSwapChain = psCurrentSwapChain->psNext) 
+       {
+               if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID)
+                       return psCurrentSwapChain;
+       }
+       return IMG_NULL;
+}
+
+static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA       *psPerProc,
+                                                                                                PVRSRV_DC_SWAPCHAIN            *psSwapChain, 
+                                                                                                PVRSRV_DC_SWAPCHAIN_REF        **ppsSwapChainRef)
+{
+       PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_DC_SWAPCHAIN_REF),
+                                        (IMG_VOID **)&psSwapChainRef, IMG_NULL,
+                                        "Display Class Swapchain Reference") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc"));
+               return  PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
+
+       
+       psSwapChain->ui32RefCount++;
+
+       
+       psSwapChainRef->psSwapChain = psSwapChain;
+       psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                 RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+                                                                                                 psSwapChainRef,
+                                                                                                 0,
+                                                                                                 &DestroyDCSwapChainRefCallBack);
+       *ppsSwapChainRef = psSwapChainRef;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA        *psPerProc,
+                                                                               IMG_HANDLE                              hDeviceKM,
+                                                                               IMG_UINT32                              ui32Flags,
+                                                                               DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+                                                                               DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+                                                                               IMG_UINT32                              ui32BufferCount,
+                                                                               IMG_UINT32                              ui32OEMFlags,
+                                                                               IMG_HANDLE                              *phSwapChainRef,
+                                                                               IMG_UINT32                              *pui32SwapChainID)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL;
+       PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+       PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+       PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 i;
+       DISPLAY_INFO sDisplayInfo;
+
+
+       if(!hDeviceKM
+       || !psDstSurfAttrib
+       || !psSrcSurfAttrib
+       || !phSwapChainRef
+       || !pui32SwapChainID)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers"));
+               return PVRSRV_ERROR_TOOMANYBUFFERS;
+       }
+
+       if (ui32BufferCount < 2)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too few buffers"));
+               return PVRSRV_ERROR_TOO_FEW_BUFFERS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+       if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
+       {
+               
+               psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
+               if( psSwapChain  ) 
+               {       
+                                          
+                       eError = PVRSRVCreateDCSwapChainRefKM(psPerProc, 
+                                                                                                 psSwapChain, 
+                                                                                                 &psSwapChainRef);
+                       if( eError != PVRSRV_OK ) 
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+                               return eError;
+                       }
+
+                       *phSwapChainRef = (IMG_HANDLE)psSwapChainRef;
+                       return PVRSRV_OK;
+               }
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query"));
+               return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;          
+       }
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_DC_SWAPCHAIN),
+                                        (IMG_VOID **)&psSwapChain, IMG_NULL,
+                                        "Display Class Swapchain") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"));
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorExit;
+       }
+       OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
+
+       
+       eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"));
+               goto ErrorExit;
+       }
+
+       
+       psSwapChain->psQueue = psQueue;
+
+       
+       for(i=0; i<ui32BufferCount; i++)
+       {
+               eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+                                                                               psDCInfo->hDevMemContext,
+                                                                               &psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain"));
+                       goto ErrorExit;
+               }
+
+               psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+
+               
+               psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+               psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+               psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+
+               
+               psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
+               psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
+
+               
+               apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+       }
+
+       psSwapChain->ui32BufferCount = ui32BufferCount;
+       psSwapChain->psDCInfo = psDCInfo;
+
+#if defined(PDUMP)
+       PDUMPCOMMENT("Allocate DC swap chain (SwapChainID == %u, BufferCount == %u)",
+                       *pui32SwapChainID,
+                       ui32BufferCount);
+       PDUMPCOMMENT("  Src surface dimensions == %u x %u",
+                       psSrcSurfAttrib->sDims.ui32Width,
+                       psSrcSurfAttrib->sDims.ui32Height);
+       PDUMPCOMMENT("  Dst surface dimensions == %u x %u",
+                       psDstSurfAttrib->sDims.ui32Width,
+                       psDstSurfAttrib->sDims.ui32Height);
+#endif
+
+       eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info"));
+               return eError;
+       }
+       
+       psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval;
+       psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval;
+
+       
+       eError =  psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+                                                                                                               ui32Flags,
+                                                                                                               psDstSurfAttrib,
+                                                                                                               psSrcSurfAttrib,
+                                                                                                               ui32BufferCount,
+                                                                                                               apsSyncData,
+                                                                                                               ui32OEMFlags,
+                                                                                                               &psSwapChain->hExtSwapChain,
+                                                                                                               &psSwapChain->ui32SwapChainID);
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
+               PDUMPCOMMENT("Swapchain allocation failed.");
+               goto ErrorExit;
+       }
+
+                          
+       eError = PVRSRVCreateDCSwapChainRefKM(psPerProc, 
+                                                                                 psSwapChain, 
+                                                                                 &psSwapChainRef);
+       if( eError != PVRSRV_OK ) 
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+               PDUMPCOMMENT("Swapchain allocation failed.");
+               goto ErrorExit;
+       }
+
+       psSwapChain->ui32RefCount = 1;
+       psSwapChain->ui32Flags = ui32Flags;
+
+       
+       if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
+       {
+               if(! psDCInfo->psDCSwapChainShared ) 
+               {
+                       psDCInfo->psDCSwapChainShared = psSwapChain;
+               } 
+               else 
+               {       
+                       PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared;
+                       psDCInfo->psDCSwapChainShared = psSwapChain;
+                       psSwapChain->psNext = psOldHead;
+               }
+       }
+
+       
+       *pui32SwapChainID = psSwapChain->ui32SwapChainID;
+
+       
+       *phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
+
+       return eError;
+
+ErrorExit:
+
+       for(i=0; i<ui32BufferCount; i++)
+       {
+               if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+               {
+                       if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+                       {
+                               PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+                       }
+               }
+       }
+
+       if(psQueue)
+       {
+               PVRSRVDestroyCommandQueueKM(psQueue);
+       }
+
+       if(psSwapChain)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+               
+       }
+
+       return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE   hDeviceKM,
+                                                                 IMG_HANDLE    hSwapChainRef,
+                                                                 IMG_RECT              *psRect)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if(!hDeviceKM || !hSwapChainRef)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+       return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+                                                                                                       psSwapChain->hExtSwapChain,
+                                                                                                       psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE   hDeviceKM,
+                                                                 IMG_HANDLE    hSwapChainRef,
+                                                                 IMG_RECT              *psRect)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if(!hDeviceKM || !hSwapChainRef)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+       return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+                                                                                                       psSwapChain->hExtSwapChain,
+                                                                                                       psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE      hDeviceKM,
+                                                                          IMG_HANDLE   hSwapChainRef,
+                                                                          IMG_UINT32   ui32CKColour)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if(!hDeviceKM || !hSwapChainRef)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+       return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+                                                                                                               psSwapChain->hExtSwapChain,
+                                                                                                               ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE      hDeviceKM,
+                                                                          IMG_HANDLE   hSwapChainRef,
+                                                                          IMG_UINT32   ui32CKColour)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if(!hDeviceKM || !hSwapChainRef)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+       return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+                                                                                                               psSwapChain->hExtSwapChain,
+                                                                                                               ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE   hDeviceKM,
+                                                                 IMG_HANDLE    hSwapChainRef,
+                                                                 IMG_UINT32    *pui32BufferCount,
+                                                                 IMG_HANDLE    *phBuffer)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+       IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+       PVRSRV_ERROR eError;
+       IMG_UINT32 i;
+
+       if(!hDeviceKM || !hSwapChainRef || !phBuffer)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+       
+       eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
+                                                                                                       psSwapChain->hExtSwapChain,
+                                                                                                       pui32BufferCount,
+                                                                                                       ahExtBuffer);
+
+       PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+       
+
+
+       for(i=0; i<*pui32BufferCount; i++)
+       {
+               psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
+               phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
+                                                                       IMG_HANDLE      hBuffer,
+                                                                       IMG_UINT32      ui32SwapInterval,
+                                                                       IMG_HANDLE      hPrivateTag,
+                                                                       IMG_UINT32      ui32ClipRectCount,
+                                                                       IMG_RECT        *psClipRect,
+                                                                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_BUFFER *psBuffer;
+       PVRSRV_QUEUE_INFO *psQueue;
+       DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+       IMG_UINT32 i;
+       IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+       IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+       IMG_UINT32 ui32NumSrcSyncs = 1;
+       PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+       PVRSRV_COMMAND *psCommand;
+       struct pvr_trcmd_flpreq *fltrace;
+
+       if(!hDeviceKM || !hBuffer || !psClipRect)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+#if defined(SUPPORT_LMA)
+       eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+       if(eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+#endif 
+
+       psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+       
+       if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval ||
+               ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid swap interval. Requested %u, Allowed range %u-%u",
+                                ui32SwapInterval, psBuffer->psSwapChain->ui32MinSwapInterval, psBuffer->psSwapChain->ui32MaxSwapInterval));
+               return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
+       }
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+       if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+       {
+               psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+                                                                                                        psBuffer->psSwapChain->hExtSwapChain,
+                                                                                                        psBuffer->sDeviceClassBuffer.hExtBuffer, 
+                                                                                                        hPrivateTag, 
+                                                                                                        &ui16SwapCommandID,
+                                                                                                        &bAddReferenceToLast);
+               
+       }
+
+#endif
+
+       
+       psQueue = psBuffer->psSwapChain->psQueue;
+
+       
+       apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+       
+
+
+       if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
+               psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
+       {
+               apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+               
+
+
+               ui32NumSrcSyncs++;
+       }
+
+       
+       eError = PVRSRVInsertCommandKM (psQueue,
+                                                                       &psCommand,
+                                                                       psDCInfo->ui32DeviceID,
+                                                                       ui16SwapCommandID,
+                                                                       0,
+                                                                       IMG_NULL,
+                                                                       ui32NumSrcSyncs,
+                                                                       apsSrcSync,
+                                                                       sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount));
+       fltrace = pvr_trcmd_reserve(PVR_TRCMD_FLPREQ, psPerProc->ui32PID,
+                                 psPerProc->name, sizeof(*fltrace));
+       pvr_trcmd_set_syn(&fltrace->src_syn[0], apsSrcSync[0]);
+       if (ui32NumSrcSyncs > 1)
+               pvr_trcmd_set_syn(&fltrace->src_syn[1], apsSrcSync[1]);
+       else
+               pvr_trcmd_clear_syn(&fltrace->src_syn[1]);
+
+       pvr_trcmd_commit(fltrace);
+
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
+               goto Exit;
+       }
+
+       
+       psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+       
+       psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+       
+       psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
+
+       
+       psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
+
+       
+       psFlipCmd->hPrivateTag = hPrivateTag;
+
+       
+       psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
+       
+       psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND)); 
+       
+       for(i=0; i<ui32ClipRectCount; i++)
+       {
+               psFlipCmd->psClipRect[i] = psClipRect[i];
+       }
+
+       
+       psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+       
+       eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
+               goto Exit;
+       }
+
+       
+
+
+
+
+
+
+
+        
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED)
+               {
+                       goto ProcessedQueues;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to process queues"));
+
+       eError = PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE;
+       goto Exit;
+
+ProcessedQueues:
+       
+       psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
+
+Exit:
+
+       if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+       {
+               eError = PVRSRV_ERROR_RETRY;
+       }
+
+#if defined(SUPPORT_LMA)
+       PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+                                                                       IMG_HANDLE      hSwapChainRef)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_QUEUE_INFO *psQueue;
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+       PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+       DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+       IMG_UINT32 ui32NumSrcSyncs = 1;
+       PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+       PVRSRV_COMMAND *psCommand;
+       IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+       IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+
+       if(!hDeviceKM || !hSwapChainRef)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+#if defined(SUPPORT_LMA)
+       eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+       if(eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+#endif 
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
+       psSwapChain = psSwapChainRef->psSwapChain;
+
+       
+       psQueue = psSwapChain->psQueue;
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+       if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+       {
+               psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+                                                                                                        psSwapChain->hExtSwapChain,
+                                                                                                        psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer, 
+                                                                                                        0, 
+                                                                                                        &ui16SwapCommandID,
+                                                                                                        &bAddReferenceToLast);
+               
+       }
+
+#endif
+
+       
+       apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
+       
+
+
+       if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
+       {
+               
+               if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
+               {
+                       apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+                       
+
+
+                       ui32NumSrcSyncs++;
+               }
+       }
+
+       
+       eError = PVRSRVInsertCommandKM (psQueue,
+                                                                       &psCommand,
+                                                                       psDCInfo->ui32DeviceID,
+                                                                       ui16SwapCommandID,
+                                                                       0,
+                                                                       IMG_NULL,
+                                                                       ui32NumSrcSyncs,
+                                                                       apsSrcSync,
+                                                                       sizeof(DISPLAYCLASS_FLIP_COMMAND));
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
+               goto Exit;
+       }
+
+       
+       psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+       
+       psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+       
+       psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+       
+       psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
+
+       
+       psFlipCmd->hPrivateTag = IMG_NULL;
+
+       
+       psFlipCmd->ui32ClipRectCount = 0;
+
+       psFlipCmd->ui32SwapInterval = 1;
+
+       
+       eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command"));
+               goto Exit;
+       }
+
+       
+
+
+
+
+
+
+        
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED)
+               {
+                       goto ProcessedQueues;
+               }
+
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to process queues"));
+       eError = PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE;
+       goto Exit;
+
+ProcessedQueues:
+       
+       psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
+
+       eError = PVRSRV_OK;
+
+Exit:
+
+       if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+       {
+               eError = PVRSRV_ERROR_RETRY;
+       }
+
+#if defined(SUPPORT_LMA)
+       PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+       return eError;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER   pfnISRHandler,
+                                                                                        IMG_VOID                       *pvISRHandlerData,
+                                                                                        IMG_UINT32                     ui32ISRSourceMask,
+                                                                                        IMG_UINT32                     ui32DeviceID)
+{
+       SYS_DATA                        *psSysData;
+       PVRSRV_DEVICE_NODE      *psDevNode;
+
+       PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
+
+       SysAcquireData(&psSysData);
+
+       
+       psDevNode = (PVRSRV_DEVICE_NODE*)
+                               List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                               &MatchDeviceKM_AnyVaCb,
+                                                                                               ui32DeviceID,
+                                                                                               IMG_TRUE);
+
+       if (psDevNode == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode"));
+               PVR_DBG_BREAK;
+               return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+       }
+
+       
+       psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
+
+       
+       psDevNode->pfnDeviceISR = pfnISRHandler;
+
+       return PVRSRV_OK;
+}
+
+static
+IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       IMG_UINT32 ui32State;
+       ui32State = va_arg(va, IMG_UINT32);
+
+       if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+       {
+               psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
+               if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice)
+               {
+                       psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State);
+               }
+       }
+}
+
+
+IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
+{
+       SYS_DATA                                        *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+                                                                               &PVRSRVSetDCState_ForEachVaCb,
+                                                                               ui32State);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
+{
+       psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE);
+       psJTable->pfnPVRSRVRegisterDCDevice = &PVRSRVRegisterDCDeviceKM;
+       psJTable->pfnPVRSRVRemoveDCDevice = &PVRSRVRemoveDCDeviceKM;
+       psJTable->pfnPVRSRVOEMFunction = &SysOEMFunction;
+       psJTable->pfnPVRSRVRegisterCmdProcList = &PVRSRVRegisterCmdProcListKM;
+       psJTable->pfnPVRSRVRemoveCmdProcList = &PVRSRVRemoveCmdProcListKM;
+#if defined(SUPPORT_MISR_IN_THREAD)
+        psJTable->pfnPVRSRVCmdComplete = &OSVSyncMISR;
+#else
+        psJTable->pfnPVRSRVCmdComplete = &PVRSRVCommandCompleteKM;
+#endif
+       psJTable->pfnPVRSRVRegisterSystemISRHandler = &PVRSRVRegisterSystemISRHandler;
+       psJTable->pfnPVRSRVRegisterPowerDevice = &PVRSRVRegisterPowerDevice;
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+       psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM;
+#endif
+
+       return IMG_TRUE;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM,
+                                                                       IMG_BOOL        bResManCallback)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+       PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+       psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+       
+       eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem);
+
+       return eError;
+}
+
+
+static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID            pvParam,
+                                                                                 IMG_UINT32    ui32Param)
+{
+       PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+       PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam;
+       psBCInfo = psBCPerContextInfo->psBCInfo;
+
+       psBCInfo->ui32RefCount--;
+       if(psBCInfo->ui32RefCount == 0)
+       {
+               IMG_UINT32 i;
+
+               
+               psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
+
+               
+               for(i=0; i<psBCInfo->ui32BufferCount; i++)
+               {
+                       if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+                       {
+                               if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+                               {
+                                       PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+                               }
+                       }
+               }
+
+               
+               if(psBCInfo->psBuffer)
+               {
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL);
+                       psBCInfo->psBuffer = IMG_NULL;
+               }
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
+       
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA     *psPerProc,
+                                                                  IMG_UINT32                           ui32DeviceID,
+                                                                  IMG_HANDLE                           hDevCookie,
+                                                                  IMG_HANDLE                           *phDeviceKM)
+{
+       PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+       PVRSRV_BUFFERCLASS_PERCONTEXT_INFO      *psBCPerContextInfo;
+       PVRSRV_DEVICE_NODE              *psDeviceNode;
+       SYS_DATA                                *psSysData;
+       IMG_UINT32                              i;
+       PVRSRV_ERROR                    eError;
+
+       if(!phDeviceKM || !hDevCookie)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       SysAcquireData(&psSysData);
+
+       
+       psDeviceNode = (PVRSRV_DEVICE_NODE*)
+                       List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                  &MatchDeviceKM_AnyVaCb,
+                                                                                  ui32DeviceID,
+                                                                                  IMG_FALSE,
+                                                                                  PVRSRV_DEVICE_CLASS_BUFFER);
+       if (!psDeviceNode)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID));
+               return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+       }
+       psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
+
+       
+
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(*psBCPerContextInfo),
+                                 (IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
+                                 "Buffer Class per Context Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
+
+       if(psBCInfo->ui32RefCount++ == 0)
+       {
+               BUFFER_INFO sBufferInfo;
+
+               psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+               
+               psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+               
+               eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device"));
+                       return eError;
+               }
+
+               
+               eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info"));
+                       return eError;
+               }
+
+               
+               psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
+               
+
+               
+               eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                                         sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
+                                                         (IMG_VOID **)&psBCInfo->psBuffer,
+                                                         IMG_NULL,
+                                                         "Array of Buffer Class Buffer");
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers"));
+                       return eError;
+               }
+               OSMemSet (psBCInfo->psBuffer,
+                                       0,
+                                       sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount);
+
+               for(i=0; i<psBCInfo->ui32BufferCount; i++)
+               {
+                       
+                       eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+                                                                               psBCInfo->hDevMemContext,
+                                                                               &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+                       if(eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
+                               goto ErrorExit;
+                       }
+
+                       psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+                       
+                       
+
+
+                       eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
+                                                                                                                       i,
+                                                                                                                       psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
+                                                                                                                       &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer);
+                       if(eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers"));
+                               goto ErrorExit;
+                       }
+
+                       
+                       psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
+                       psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
+                       psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
+               }
+       }
+
+       psBCPerContextInfo->psBCInfo = psBCInfo;
+       psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                        RESMAN_TYPE_BUFFERCLASS_DEVICE,
+                                                                                                        psBCPerContextInfo,
+                                                                                                        0,
+                                                                                                        &CloseBCDeviceCallBack);
+
+       
+       *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       
+       for(i=0; i<psBCInfo->ui32BufferCount; i++)
+       {
+               if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+               {
+                       if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+                       {
+                               PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+                       }
+               }
+       }
+
+       
+       if(psBCInfo->psBuffer)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+               psBCInfo->psBuffer = IMG_NULL;
+       }
+
+       return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
+                                                               BUFFER_INFO *psBufferInfo)
+{
+       PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+       PVRSRV_ERROR                    eError;
+
+       if(!hDeviceKM || !psBufferInfo)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+       eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo);
+
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info"));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
+                                                                 IMG_UINT32 ui32BufferIndex,
+                                                                 IMG_HANDLE *phBuffer)
+{
+       PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+       if(!hDeviceKM || !phBuffer)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+       if(ui32BufferIndex < psBCInfo->ui32BufferCount)
+       {
+               *phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex];
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
+{
+       psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+       psJTable->pfnPVRSRVRegisterBCDevice = &PVRSRVRegisterBCDeviceKM;
+       psJTable->pfnPVRSRVScheduleDevices = &PVRSRVScheduleDevicesKM;
+       psJTable->pfnPVRSRVRemoveBCDevice = &PVRSRVRemoveBCDeviceKM;
+
+       return IMG_TRUE;
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/deviceid.h b/drivers/staging/mrst/pvr/services4/srvkm/common/deviceid.h
new file mode 100644 (file)
index 0000000..b6fe921
--- /dev/null
@@ -0,0 +1,36 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __DEVICEID_H__
+#define __DEVICEID_H__
+
+#include "services.h"
+#include "syscommon.h"
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/devicemem.c b/drivers/staging/mrst/pvr/services4/srvkm/common/devicemem.c
new file mode 100644 (file)
index 0000000..f51d632
--- /dev/null
@@ -0,0 +1,1597 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+#include "pvr_bridge_km.h"
+
+#include "pvr_trace_cmd.h"
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE          hDevCookie,
+                                                                       IMG_HANDLE              hDevMemHeap,
+                                                                       IMG_UINT32              ui32Flags,
+                                                                       IMG_SIZE_T              ui32Size,
+                                                                       IMG_SIZE_T              ui32Alignment,
+                                                                       PVRSRV_KERNEL_MEM_INFO  **ppsMemInfo);
+
+typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_
+{
+       
+       PVRSRV_KERNEL_MEM_INFO  *psMemInfo;
+       
+       PVRSRV_KERNEL_MEM_INFO  *psSrcMemInfo;
+} RESMAN_MAP_DEVICE_MEM_DATA;
+
+typedef struct _PVRSRV_DC_MAPINFO_
+{
+       PVRSRV_KERNEL_MEM_INFO  *psMemInfo;
+       PVRSRV_DEVICE_NODE              *psDeviceNode;
+       IMG_UINT32                              ui32RangeIndex;
+       IMG_UINT32                              ui32TilingStride;
+} PVRSRV_DC_MAPINFO;
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+                                                                                                       PVRSRV_HEAP_INFO *psHeapInfo)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_UINT32 ui32HeapCount;
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+       IMG_UINT32 i;
+
+       if (hDevCookie == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid"));
+               PVR_DBG_BREAK;
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+       
+       ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+       psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+       
+       PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+       
+       for(i=0; i<ui32HeapCount; i++)
+       {
+               
+               psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+               psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+               psHeapInfo[i].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+               psHeapInfo[i].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+               psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+       }
+
+       for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+       {
+               OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo));
+               psHeapInfo[i].ui32HeapID = (IMG_UINT32)PVRSRV_UNDEFINED_HEAP_ID;
+       }
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE                                    hDevCookie,
+                                                                                                                PVRSRV_PER_PROCESS_DATA        *psPerProc,
+                                                                                                                IMG_HANDLE                             *phDevMemContext,
+                                                                                                                IMG_UINT32                             *pui32ClientHeapCount,
+                                                                                                                PVRSRV_HEAP_INFO                       *psHeapInfo,
+                                                                                                                IMG_BOOL                                       *pbCreated,
+                                                                                                                IMG_BOOL                                       *pbShared)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+       IMG_HANDLE hDevMemContext;
+       IMG_HANDLE hDevMemHeap;
+       IMG_DEV_PHYADDR sPDDevPAddr;
+       IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+       PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+       if (hDevCookie == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVCreateDeviceMemContextKM: hDevCookie invalid"));
+               PVR_DBG_BREAK;
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+       
+
+       ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+       psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+       
+
+       PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+       
+
+       hDevMemContext = BM_CreateContext(psDeviceNode,
+                                                                         &sPDDevPAddr,
+                                                                         psPerProc,
+                                                                         pbCreated);
+       if (hDevMemContext == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDeviceMemContextKM: Failed BM_CreateContext"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       
+       for(i=0; i<ui32HeapCount; i++)
+       {
+               switch(psDeviceMemoryHeap[i].DevMemHeapType)
+               {
+                       case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+                       {
+                               
+                               psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+                               psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+                               psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+                               psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+                               psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+                               pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+                               ui32ClientHeapCount++;
+                               break;
+                       }
+                       case DEVICE_MEMORY_HEAP_PERCONTEXT:
+                       {
+                               hDevMemHeap = BM_CreateHeap(hDevMemContext,
+                                                                                       &psDeviceMemoryHeap[i]);
+
+                               
+                               psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+                               psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+                               psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+                               psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+                               psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+                               pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+                               ui32ClientHeapCount++;
+                               break;
+                       }
+               }
+       }
+
+       
+       *pui32ClientHeapCount = ui32ClientHeapCount;
+       *phDevMemContext = hDevMemContext;
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+                                                                                                                 IMG_HANDLE hDevMemContext,
+                                                                                                                 IMG_BOOL *pbDestroyed)
+{
+       PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+       return BM_DestroyContext(hDevMemContext, pbDestroyed);
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE                                      hDevCookie,
+                                                                                                                IMG_HANDLE                             hDevMemContext,
+                                                                                                                IMG_UINT32                             *pui32ClientHeapCount,
+                                                                                                                PVRSRV_HEAP_INFO                       *psHeapInfo,
+                                                                                                                IMG_BOOL                                       *pbShared)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+       IMG_HANDLE hDevMemHeap;
+       IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+       PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+       if (hDevCookie == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid"));
+               PVR_DBG_BREAK;
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+       
+
+       ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+       psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+       
+
+       PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+       
+       for(i=0; i<ui32HeapCount; i++)
+       {
+               switch(psDeviceMemoryHeap[i].DevMemHeapType)
+               {
+                       case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+                       {
+                               
+                               psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+                               psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+                               psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+                               psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+                               psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+                               pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+                               ui32ClientHeapCount++;
+                               break;
+                       }
+                       case DEVICE_MEMORY_HEAP_PERCONTEXT:
+                       {
+                               hDevMemHeap = BM_CreateHeap(hDevMemContext,
+                                                                                       &psDeviceMemoryHeap[i]);
+
+                               
+                               psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+                               psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+                               psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+                               psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+                               psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+                               pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+                               ui32ClientHeapCount++;
+                               break;
+                       }
+               }
+       }
+
+       
+       *pui32ClientHeapCount = ui32ClientHeapCount;
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE          hDevCookie,
+                                                                       IMG_HANDLE              hDevMemHeap,
+                                                                       IMG_UINT32              ui32Flags,
+                                                                       IMG_SIZE_T              ui32Size,
+                                                                       IMG_SIZE_T              ui32Alignment,
+                                                                       PVRSRV_KERNEL_MEM_INFO  **ppsMemInfo)
+{
+       PVRSRV_KERNEL_MEM_INFO  *psMemInfo;
+       BM_HANDLE               hBuffer;
+       
+       PVRSRV_MEMBLK   *psMemBlock;
+       IMG_BOOL                bBMError;
+
+       PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+       *ppsMemInfo = IMG_NULL;
+
+       if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                                       sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                       (IMG_VOID **)&psMemInfo, IMG_NULL,
+                                       "Kernel Memory Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: Failed to alloc memory for block"));
+               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+       }
+
+       OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+       psMemBlock = &(psMemInfo->sMemBlk);
+
+       
+       psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+       bBMError = BM_Alloc (hDevMemHeap,
+                                                       IMG_NULL,
+                                                       ui32Size,
+                                                       &psMemInfo->ui32Flags,
+                                                       IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment),
+                                                       &hBuffer);
+
+       if (!bBMError)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed"));
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+               
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       
+       psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+       psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+       
+       psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+       
+
+       psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+       psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+
+       psMemInfo->ui32AllocSize = ui32Size;
+
+       
+       psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+       
+       *ppsMemInfo = psMemInfo;
+
+       
+       return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, IMG_BOOL bFromAllocator)
+{
+       BM_HANDLE               hBuffer;
+
+       if (!psMemInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+       if (bFromAllocator)
+               BM_Free(hBuffer, psMemInfo->ui32Flags);
+       else
+               BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+
+       
+       if ((psMemInfo->pvSysBackupBuffer) && bFromAllocator)
+       {
+               
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+               psMemInfo->pvSysBackupBuffer = IMG_NULL;
+       }
+
+       if (psMemInfo->ui32RefCount == 0)
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+       return(PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+       BM_HANDLE               hBuffer;
+
+       if (!psMemInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       hBuffer = psMemInfo->sMemBlk.hBuffer;
+       
+       BM_Free(hBuffer, psMemInfo->ui32Flags);
+
+       if(psMemInfo->pvSysBackupBuffer)
+       {
+               
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+               psMemInfo->pvSysBackupBuffer = IMG_NULL;
+       }
+
+       OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+       
+
+       return(PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE                                     hDevCookie,
+                                                                                               IMG_HANDLE                                      hDevMemContext,
+                                                                                               PVRSRV_KERNEL_SYNC_INFO         **ppsKernelSyncInfo)
+{
+       IMG_HANDLE hSyncDevMemHeap;
+       DEVICE_MEMORY_INFO *psDevMemoryInfo;
+       BM_CONTEXT *pBMContext;
+       PVRSRV_ERROR eError;
+       PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+       PVRSRV_SYNC_DATA *psSyncData;
+
+       eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                                               sizeof(PVRSRV_KERNEL_SYNC_INFO),
+                                               (IMG_VOID **)&psKernelSyncInfo, IMG_NULL,
+                                               "Kernel Synchronization Info");
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       psKernelSyncInfo->ui32RefCount = 0;
+
+#ifdef CONFIG_PVR_TRACE_CMD
+       INIT_LIST_HEAD(&psKernelSyncInfo->link);
+       psKernelSyncInfo->counter_digest = 0;
+#endif
+       
+       pBMContext = (BM_CONTEXT*)hDevMemContext;
+       psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+       
+       hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->ui32SyncHeapID].hDevMemHeap;
+
+       
+
+
+       eError = AllocDeviceMem(hDevCookie,
+                                                       hSyncDevMemHeap,
+                                                       PVRSRV_MEM_CACHE_CONSISTENT,
+                                                       sizeof(PVRSRV_SYNC_DATA),
+                                                       sizeof(IMG_UINT32),
+                                                       &psKernelSyncInfo->psSyncDataMemInfoKM);
+
+       if (eError != PVRSRV_OK)
+       {
+
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+               
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       
+       psKernelSyncInfo->psSyncData = psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+       psSyncData = psKernelSyncInfo->psSyncData;
+
+       psSyncData->ui32WriteOpsPending = 0;
+       psSyncData->ui32WriteOpsComplete = 0;
+       psSyncData->ui32ReadOpsPending = 0;
+       psSyncData->ui32ReadOpsComplete = 0;
+       psSyncData->ui32LastOpDumpVal = 0;
+       psSyncData->ui32LastReadOpDumpVal = 0;
+
+#if defined(PDUMP)
+       PDUMPCOMMENT("Allocating kernel sync object");
+       PDUMPMEM(psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM,
+                       psKernelSyncInfo->psSyncDataMemInfoKM,
+                       0,
+                       psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize,
+                       PDUMP_FLAGS_CONTINUOUS,
+                       MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+       psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+       psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+
+       
+       psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = IMG_NULL;
+
+       
+       *ppsKernelSyncInfo = psKernelSyncInfo;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+       PVRSRV_ERROR eError;
+       
+       if (psKernelSyncInfo->ui32RefCount != 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "oops: sync info ref count not zero at destruction"));
+               
+               return PVRSRV_ERROR_OUT_OF_MEMORY; 
+       }
+
+       /*
+        * TODO: arrange for the per proc info to be passed to this func, so
+        * we can trace the pid and proc name.
+        */
+       pvr_trcmd_remove_syn(0, "n/a", psKernelSyncInfo);
+
+       eError = FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+       (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+       
+
+       return eError;
+}
+
+static IMG_VOID freeWrapped(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+       IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+       
+       if(psMemInfo->sMemBlk.psIntSysPAddr)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+               psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+       }
+
+       if(hOSWrapMem)
+       {
+               OSReleasePhysPageAddr(hOSWrapMem);
+       }
+}
+
+static PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                                                 IMG_UINT32    ui32Param,
+                                                                                 IMG_BOOL      bFromAllocator)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       
+       psMemInfo->ui32RefCount--;
+
+       if (psMemInfo->ui32RefCount == 0)
+       {
+               if(psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED)
+               {
+                       IMG_HANDLE hMemInfo = IMG_NULL;
+
+
+                       eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+                                       &hMemInfo,
+                                       psMemInfo,
+                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+                       if(eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
+                               return eError;
+                       }
+
+
+                       eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+                                       hMemInfo,
+                                       PVRSRV_HANDLE_TYPE_MEM_INFO);
+                       if(eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
+                               return eError;
+                       }
+               }
+
+               switch(psMemInfo->memType)
+               {
+                       
+                       case PVRSRV_MEMTYPE_WRAPPED:
+                               freeWrapped(psMemInfo);
+                       case PVRSRV_MEMTYPE_DEVICE:
+                               if (psMemInfo->psKernelSyncInfo)
+                               {
+                                       psMemInfo->psKernelSyncInfo->ui32RefCount--;
+
+                                       if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+                                       {
+                                               eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+                                       }
+                               }
+
+                       case PVRSRV_MEMTYPE_DEVICECLASS:
+                               break;
+                       default:
+                               PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: Unknown memType"));
+                               eError = PVRSRV_ERROR_INVALID_MEMINFO;
+               }
+       }
+
+       
+       
+       eError = FreeDeviceMem2(psMemInfo, bFromAllocator);
+
+       return eError;
+}
+
+static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID            pvParam,
+                                                                                 IMG_UINT32    ui32Param)
+{
+       PVRSRV_KERNEL_MEM_INFO  *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+       return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE                             hDevCookie,
+                                                                                               PVRSRV_KERNEL_MEM_INFO  *psMemInfo)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+       if (!psMemInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (psMemInfo->sMemBlk.hResItem != IMG_NULL)
+       {
+               eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+       }
+       else
+       {
+               
+               eError = FreeDeviceMemCallBack(psMemInfo, 0);
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE                                   hDevCookie,
+                                                                                                PVRSRV_PER_PROCESS_DATA        *psPerProc,
+                                                                                                IMG_HANDLE                                     hDevMemHeap,
+                                                                                                IMG_UINT32                                     ui32Flags,
+                                                                                                IMG_SIZE_T                                     ui32Size,
+                                                                                                IMG_SIZE_T                                     ui32Alignment,
+                                                                                                PVRSRV_KERNEL_MEM_INFO         **ppsMemInfo)
+{
+       PVRSRV_KERNEL_MEM_INFO  *psMemInfo;
+       PVRSRV_ERROR                    eError;
+       BM_HEAP                                 *psBMHeap;
+       IMG_HANDLE                              hDevMemContext;
+
+       if (!hDevMemHeap ||
+               (ui32Size == 0))
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+       {
+                
+               if (((ui32Size % HOST_PAGESIZE()) != 0) ||
+                       ((ui32Alignment % HOST_PAGESIZE()) != 0))
+               {
+                       return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+       }
+
+       eError = AllocDeviceMem(hDevCookie,
+                                                       hDevMemHeap,
+                                                       ui32Flags,
+                                                       ui32Size,
+                                                       ui32Alignment,
+                                                       &psMemInfo);
+
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       psBMHeap = (BM_HEAP*)hDevMemHeap;
+       if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB)
+               psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie, psMemInfo->ui32AllocSize, IMG_TRUE);
+#endif
+
+       if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+       {
+               psMemInfo->psKernelSyncInfo = IMG_NULL;
+       }
+       else
+       {
+               
+
+
+               psBMHeap = (BM_HEAP*)hDevMemHeap;
+               hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+               eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+                                                                          hDevMemContext,
+                                                                          &psMemInfo->psKernelSyncInfo);
+               if(eError != PVRSRV_OK)
+               {
+                       goto free_mainalloc;
+               }
+               psMemInfo->psKernelSyncInfo->ui32RefCount++;
+#if defined(PVRSRV_RESOURCE_PROFILING)
+               if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB)
+                       psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie,
+                                               psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize, IMG_TRUE);
+#endif
+       }
+
+       
+       *ppsMemInfo = psMemInfo;
+
+       if (ui32Flags & PVRSRV_MEM_NO_RESMAN)
+       {
+               psMemInfo->sMemBlk.hResItem = IMG_NULL;
+       }
+       else
+       {
+               
+               psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                               RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+                                                                                                               psMemInfo,
+                                                                                                               0,
+                                                                                                               &FreeDeviceMemCallBack);
+               if (psMemInfo->sMemBlk.hResItem == IMG_NULL)
+               {
+                       
+                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                       goto free_mainalloc;
+               }
+       }
+
+       
+       psMemInfo->ui32RefCount++;
+
+       psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE;
+
+       
+       return (PVRSRV_OK);
+
+free_mainalloc:
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB)
+               psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie,
+                                       psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize, IMG_FALSE);
+#endif
+       FreeDeviceMem(psMemInfo);
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE              hDevCookie,
+                                                                                                         PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevCookie;
+
+       PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+       if (!psMemInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = ResManDissociateRes(psMemInfo->sMemBlk.hResItem, psDeviceNode->hResManContext);
+
+       PVR_ASSERT(eError == PVRSRV_OK);
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+                                                                                                  IMG_SIZE_T *pui32Total,
+                                                                                                  IMG_SIZE_T *pui32Free,
+                                                                                                  IMG_SIZE_T *pui32LargestBlock)
+{
+       
+
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+       PVR_UNREFERENCED_PARAMETER(pui32Total);
+       PVR_UNREFERENCED_PARAMETER(pui32Free);
+       PVR_UNREFERENCED_PARAMETER(pui32LargestBlock);
+
+       return PVRSRV_OK;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO      *psMemInfo)
+{
+       if (!psMemInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID  pvParam,
+                                                                                       IMG_UINT32      ui32Param)
+{
+       PVRSRV_KERNEL_MEM_INFO  *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+
+       return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE                             hDevCookie,
+                                                                                               PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                                                                               IMG_HANDLE                              hDevMemContext,
+                                                                                               IMG_SIZE_T                              ui32ByteSize,
+                                                                                               IMG_SIZE_T                              ui32PageOffset,
+                                                                                               IMG_BOOL                                bPhysContig,
+                                                                                               IMG_SYS_PHYADDR                 *psExtSysPAddr,
+                                                                                               IMG_VOID                                *pvLinAddr,
+                                                                                               IMG_UINT32                              ui32Flags,
+                                                                                               PVRSRV_KERNEL_MEM_INFO  **ppsMemInfo)
+{
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+       DEVICE_MEMORY_INFO  *psDevMemoryInfo;
+       IMG_SIZE_T                      ui32HostPageSize = HOST_PAGESIZE();
+       IMG_HANDLE                      hDevMemHeap = IMG_NULL;
+       PVRSRV_DEVICE_NODE* psDeviceNode;
+       BM_HANDLE                       hBuffer;
+       PVRSRV_MEMBLK           *psMemBlock;
+       IMG_BOOL                        bBMError;
+       BM_HEAP                         *psBMHeap;
+       PVRSRV_ERROR            eError;
+       IMG_VOID                        *pvPageAlignedCPUVAddr;
+       IMG_SYS_PHYADDR         *psIntSysPAddr = IMG_NULL;
+       IMG_HANDLE                      hOSWrapMem = IMG_NULL;
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;    
+       IMG_UINT32              i;
+        IMG_SIZE_T              ui32PageCount = 0;
+       
+       
+       psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie;
+       PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+       if (psDeviceNode == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if(pvLinAddr)
+       {
+               
+               ui32PageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1);
+
+               
+               ui32PageCount = HOST_PAGEALIGN(ui32ByteSize + ui32PageOffset) / ui32HostPageSize;
+               pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - ui32PageOffset);
+
+               
+               if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+                                               (IMG_VOID **)&psIntSysPAddr, IMG_NULL,
+                                               "Array of Page Addresses") != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+
+               eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
+                                                                               ui32PageCount * ui32HostPageSize,
+                                                                               psIntSysPAddr,
+                                                                               &hOSWrapMem);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                       goto ErrorExitPhase1;
+               }
+
+               
+               psExtSysPAddr = psIntSysPAddr;
+
+               
+
+               bPhysContig = IMG_FALSE;
+       }
+       else
+       {
+               
+       }
+       
+       
+       psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+       psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+       for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+       {
+               if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+               {
+                       if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+                       {
+                               
+                               hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+                       }
+                       else
+                       {
+                               hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+                       }
+                       break;
+               }
+       }
+
+       if(hDevMemHeap == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: unable to find mapping heap"));
+               eError = PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP;
+               goto ErrorExitPhase2;
+       }
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                       sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                       (IMG_VOID **)&psMemInfo, IMG_NULL,
+                                       "Kernel Memory Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorExitPhase2;
+       }
+
+       OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+       psMemInfo->ui32Flags = ui32Flags;
+
+       psMemBlock = &(psMemInfo->sMemBlk);
+
+       bBMError = BM_Wrap(hDevMemHeap,
+                                          ui32ByteSize,
+                                          ui32PageOffset,
+                                          bPhysContig,
+                                          psExtSysPAddr,
+                                          IMG_NULL,
+                                          &psMemInfo->ui32Flags,
+                                          &hBuffer);
+       if (!bBMError)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
+               eError = PVRSRV_ERROR_BAD_MAPPING;
+               goto ErrorExitPhase3;
+       }
+
+       
+       psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+       psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+       psMemBlock->hOSWrapMem = hOSWrapMem;
+       psMemBlock->psIntSysPAddr = psIntSysPAddr;
+
+       
+       psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+       
+       psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+       psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+       psMemInfo->ui32AllocSize = ui32ByteSize;
+
+       
+
+       psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+       
+
+
+       psBMHeap = (BM_HEAP*)hDevMemHeap;
+       hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+       eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+                                                                       hDevMemContext,
+                                                                       &psMemInfo->psKernelSyncInfo);
+       if(eError != PVRSRV_OK)
+       {
+               goto ErrorExitPhase4;
+       }
+
+       psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+       
+       psMemInfo->ui32RefCount++;
+
+       psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED;
+
+       
+       psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                       RESMAN_TYPE_DEVICEMEM_WRAP,
+                                                                                                       psMemInfo,
+                                                                                                       0,
+                                                                                                       &UnwrapExtMemoryCallBack);
+
+       
+       *ppsMemInfo = psMemInfo;
+
+       return PVRSRV_OK;
+
+       
+
+ErrorExitPhase4:
+       if(psMemInfo)
+       {
+               FreeDeviceMem(psMemInfo);
+               
+
+
+               psMemInfo = IMG_NULL;
+       }
+
+ErrorExitPhase3:
+       if(psMemInfo)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+               
+       }
+
+ErrorExitPhase2:
+       if(psIntSysPAddr)
+       {
+               OSReleasePhysPageAddr(hOSWrapMem);
+       }
+
+ErrorExitPhase1:
+       if(psIntSysPAddr)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL);
+               
+       }
+       
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+       if (!psMemInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
+                                                                                         IMG_UINT32 ui32Param)
+{
+       PVRSRV_ERROR                            eError;
+       RESMAN_MAP_DEVICE_MEM_DATA      *psMapData = pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       if(psMapData->psMemInfo->sMemBlk.psIntSysPAddr)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMapData->psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+               psMapData->psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+       }
+
+       if( psMapData->psMemInfo->psKernelSyncInfo )
+       {
+               psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount--;
+               if (psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+               {
+                       eError = PVRSRVFreeSyncInfoKM(psMapData->psMemInfo->psKernelSyncInfo);
+                       if(eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free sync info"));
+                               return eError;
+                       }
+               }
+       }
+       
+       eError = FreeDeviceMem(psMapData->psMemInfo);
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free DST meminfo"));
+               return eError;
+       }
+
+       
+       eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0, IMG_FALSE);
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+       
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA      *psPerProc,
+                                                                                                 PVRSRV_KERNEL_MEM_INFO        *psSrcMemInfo,
+                                                                                                 IMG_HANDLE                            hDstDevMemHeap,
+                                                                                                 PVRSRV_KERNEL_MEM_INFO        **ppsDstMemInfo)
+{
+       PVRSRV_ERROR                            eError;
+       IMG_UINT32                                      i;
+       IMG_SIZE_T                                      ui32PageCount, ui32PageOffset;
+       IMG_SIZE_T                                      ui32HostPageSize = HOST_PAGESIZE();
+       IMG_SYS_PHYADDR                         *psSysPAddr = IMG_NULL;
+       IMG_DEV_PHYADDR                         sDevPAddr;
+       BM_BUF                                          *psBuf;
+       IMG_DEV_VIRTADDR                        sDevVAddr;
+       PVRSRV_KERNEL_MEM_INFO          *psMemInfo = IMG_NULL;
+       BM_HANDLE                                       hBuffer;
+       PVRSRV_MEMBLK                           *psMemBlock;
+       IMG_BOOL                                        bBMError;
+       PVRSRV_DEVICE_NODE                      *psDeviceNode;
+       IMG_VOID                                        *pvPageAlignedCPUVAddr;
+       RESMAN_MAP_DEVICE_MEM_DATA      *psMapData = IMG_NULL;
+
+       
+       if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       *ppsDstMemInfo = IMG_NULL;
+
+       ui32PageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
+       ui32PageCount = HOST_PAGEALIGN(psSrcMemInfo->ui32AllocSize + ui32PageOffset) / ui32HostPageSize;
+       pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psSrcMemInfo->pvLinAddrKM - ui32PageOffset);
+
+       
+
+
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                       ui32PageCount*sizeof(IMG_SYS_PHYADDR),
+                                       (IMG_VOID **)&psSysPAddr, IMG_NULL,
+                                       "Array of Page Addresses") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       psBuf = psSrcMemInfo->sMemBlk.hBuffer;
+
+       
+       psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+       
+       sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(ui32PageOffset);
+       for(i=0; i<ui32PageCount; i++)
+       {
+               BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+
+               
+               psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr);
+
+               
+               sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
+       }
+
+       
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                       sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
+                                       (IMG_VOID **)&psMapData, IMG_NULL,
+                                       "Resource Manager Map Data") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data"));
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorExit;
+       }
+
+
+       if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                                       sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                       (IMG_VOID **)&psMemInfo, IMG_NULL,
+                                       "Kernel Memory Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorExit;
+       }
+
+       OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+       psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags;
+
+       psMemBlock = &(psMemInfo->sMemBlk);
+
+       bBMError = BM_Wrap(hDstDevMemHeap,
+                                          psSrcMemInfo->ui32AllocSize,
+                                          ui32PageOffset,
+                                          IMG_FALSE,
+                                          psSysPAddr,
+                                          pvPageAlignedCPUVAddr,
+                                          &psMemInfo->ui32Flags,
+                                          &hBuffer);
+
+       if (!bBMError)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: BM_Wrap Failed"));
+               eError = PVRSRV_ERROR_BAD_MAPPING;
+               goto ErrorExit;
+       }
+
+       
+       psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+       psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+       
+       psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+       
+       psMemBlock->psIntSysPAddr = psSysPAddr;
+
+       
+       psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
+
+       
+       psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+       psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize;
+       psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
+
+       
+       if( psMemInfo->psKernelSyncInfo )
+               psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+       
+
+       psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+       
+       psMemInfo->ui32RefCount++;
+
+       
+       psSrcMemInfo->ui32RefCount++;
+
+       
+       BM_Export(psSrcMemInfo->sMemBlk.hBuffer);
+
+       psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED;
+
+       
+       psMapData->psMemInfo = psMemInfo;
+       psMapData->psSrcMemInfo = psSrcMemInfo;
+
+       
+       psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                       RESMAN_TYPE_DEVICEMEM_MAPPING,
+                                                                                                       psMapData,
+                                                                                                       0,
+                                                                                                       &UnmapDeviceMemoryCallBack);
+
+       *ppsDstMemInfo = psMemInfo;
+
+       return PVRSRV_OK;
+
+       
+
+ErrorExit:
+
+       if(psSysPAddr)
+       {
+               
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL);
+               
+       }
+
+       if(psMemInfo)
+       {
+               
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+               
+       }
+
+       if(psMapData)
+       {
+               
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+               
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+       if (!psMemInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID   pvParam,
+                                                                                                  IMG_UINT32   ui32Param)
+{
+       PVRSRV_DC_MAPINFO *psDCMapInfo = pvParam;
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       psMemInfo = psDCMapInfo->psMemInfo;
+
+#if defined(SUPPORT_MEMORY_TILING)
+       if(psDCMapInfo->ui32TilingStride > 0)
+       {
+               PVRSRV_DEVICE_NODE *psDeviceNode = psDCMapInfo->psDeviceNode;
+
+               if (psDeviceNode->pfnFreeMemTilingRange(psDeviceNode,
+                                                                                               psDCMapInfo->ui32RangeIndex) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceClassMemoryCallBack: FreeMemTilingRange failed"));
+               }
+       }
+#endif
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), psDCMapInfo, IMG_NULL);
+
+       return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                                                                                          IMG_HANDLE                           hDevMemContext,
+                                                                                                          IMG_HANDLE                           hDeviceClassBuffer,
+                                                                                                          PVRSRV_KERNEL_MEM_INFO       **ppsMemInfo,
+                                                                                                          IMG_HANDLE                           *phOSMapInfo)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DEVICE_NODE* psDeviceNode;
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+       PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+       IMG_SYS_PHYADDR *psSysPAddr;
+       IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+       IMG_BOOL bPhysContig;
+       BM_CONTEXT *psBMContext;
+       DEVICE_MEMORY_INFO *psDevMemoryInfo;
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+       IMG_HANDLE hDevMemHeap = IMG_NULL;
+       IMG_SIZE_T ui32ByteSize;
+       IMG_SIZE_T ui32Offset;
+       IMG_SIZE_T ui32PageSize = HOST_PAGESIZE();
+       BM_HANDLE               hBuffer;
+       PVRSRV_MEMBLK   *psMemBlock;
+       IMG_BOOL                bBMError;
+       IMG_UINT32 i;
+       PVRSRV_DC_MAPINFO *psDCMapInfo = IMG_NULL;
+
+       if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                       sizeof(PVRSRV_DC_MAPINFO),
+                                       (IMG_VOID **)&psDCMapInfo, IMG_NULL,
+                                       "PVRSRV_DC_MAPINFO") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for psDCMapInfo"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       OSMemSet(psDCMapInfo, 0, sizeof(PVRSRV_DC_MAPINFO));
+
+       psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer;
+
+       
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+       eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice,
+                                                                                                  psDeviceClassBuffer->hExtBuffer,
+                                                                                                  &psSysPAddr,
+                                                                                                  &ui32ByteSize,
+                                                                                                  &pvCPUVAddr,
+                                                                                                  phOSMapInfo,
+                                                                                                  &bPhysContig,
+                                                                                                  &psDCMapInfo->ui32TilingStride);
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address"));
+               goto ErrorExitPhase1;
+       }
+
+       
+       psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext;
+       psDeviceNode = psBMContext->psDeviceNode;
+       psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+       psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+       for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+       {
+               if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+               {
+                       if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+                       {
+                               
+                               hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+                       }
+                       else
+                       {
+                               hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+                       }
+                       break;
+               }
+       }
+
+       if(hDevMemHeap == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap"));
+               eError = PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE;
+               goto ErrorExitPhase1;
+       }
+
+       
+       ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1);
+       pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset);
+
+       eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                                       sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                       (IMG_VOID **)&psMemInfo, IMG_NULL,
+                                       "Kernel Memory Info");
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block"));
+               goto ErrorExitPhase1;
+       }
+
+       OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+       psMemBlock = &(psMemInfo->sMemBlk);
+
+       bBMError = BM_Wrap(hDevMemHeap,
+                                          ui32ByteSize,
+                                          ui32Offset,
+                                          bPhysContig,
+                                          psSysPAddr,
+                                          pvPageAlignedCPUVAddr,
+                                          &psMemInfo->ui32Flags,
+                                          &hBuffer);
+
+       if (!bBMError)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
+               
+               eError = PVRSRV_ERROR_BAD_MAPPING;
+               goto ErrorExitPhase2;
+       }
+
+       
+       psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+       psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+       
+       psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+       
+
+       psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+       
+       psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+       psMemInfo->ui32AllocSize = ui32ByteSize;
+       psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
+
+       
+
+       psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+       
+       psDCMapInfo->psMemInfo = psMemInfo;
+
+#if defined(SUPPORT_MEMORY_TILING)
+       psDCMapInfo->psDeviceNode = psDeviceNode;
+
+       if(psDCMapInfo->ui32TilingStride > 0)
+       {
+               
+               eError = psDeviceNode->pfnAllocMemTilingRange(psDeviceNode,
+                                                                                                               psMemInfo,
+                                                                                                               psDCMapInfo->ui32TilingStride,
+                                                                                                               &psDCMapInfo->ui32RangeIndex);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: AllocMemTilingRange failed"));
+                       goto ErrorExitPhase3;
+               }
+       }
+#endif
+
+       
+       psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                       RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+                                                                                                       psDCMapInfo,
+                                                                                                       0,
+                                                                                                       &UnmapDeviceClassMemoryCallBack);
+
+       psMemInfo->ui32RefCount++;
+
+       psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS;
+
+       
+       *ppsMemInfo = psMemInfo;
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+       PDUMPCOMMENT("Dump display surface");
+       PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->ui32AllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping);
+#endif
+       return PVRSRV_OK;
+
+#if defined(SUPPORT_MEMORY_TILING)
+ErrorExitPhase3:
+       if(psMemInfo)
+       {
+               FreeDeviceMem(psMemInfo);
+               
+
+
+               psMemInfo = IMG_NULL;
+       }
+#endif
+
+ErrorExitPhase2:
+       if(psMemInfo)
+       {
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+       }
+
+ErrorExitPhase1:
+       if(psDCMapInfo)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psDCMapInfo, IMG_NULL);
+       }
+
+       return eError;
+}
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+PVRSRV_KERNEL_MEM_INFO* PVRSRVGetMapMemInfo(IMG_VOID *psMap)
+{
+       RESMAN_MAP_DEVICE_MEM_DATA      *psMapData = psMap;
+       if (psMapData)
+               return psMapData->psMemInfo;
+       else
+               return IMG_NULL;
+}
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/handle.c b/drivers/staging/mrst/pvr/services4/srvkm/common/handle.c
new file mode 100644 (file)
index 0000000..5e34af5
--- /dev/null
@@ -0,0 +1,1723 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifdef PVR_SECURE_HANDLES
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "handle.h"
+
+#ifdef DEBUG
+#define        HANDLE_BLOCK_SHIFT      2
+#else
+#define        HANDLE_BLOCK_SHIFT      8
+#endif
+
+#define        DIVIDE_BY_BLOCK_SIZE(i)         (((IMG_UINT32)(i)) >> HANDLE_BLOCK_SHIFT)
+#define        MULTIPLY_BY_BLOCK_SIZE(i)       (((IMG_UINT32)(i)) << HANDLE_BLOCK_SHIFT)
+
+#define HANDLE_BLOCK_SIZE       MULTIPLY_BY_BLOCK_SIZE(1)
+#define        HANDLE_SUB_BLOCK_MASK   (HANDLE_BLOCK_SIZE - 1)
+#define        HANDLE_BLOCK_MASK       (~(HANDLE_SUB_BLOCK_MASK))
+
+#define        HANDLE_HASH_TAB_INIT_SIZE       32
+
+#define        INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+#define        INDEX_TO_HANDLE(i) ((IMG_HANDLE)((i) + 1))
+#define        HANDLE_TO_INDEX(h) ((IMG_UINT32)(h) - 1)
+
+#define        INDEX_TO_BLOCK_INDEX(i)         DIVIDE_BY_BLOCK_SIZE(i)
+#define BLOCK_INDEX_TO_INDEX(i)                MULTIPLY_BY_BLOCK_SIZE(i)
+#define INDEX_TO_SUB_BLOCK_INDEX(i)    ((i) & HANDLE_SUB_BLOCK_MASK)
+
+#define INDEX_TO_INDEX_STRUCT_PTR(psArray, i) (&((psArray)[INDEX_TO_BLOCK_INDEX(i)]))
+#define        BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i) INDEX_TO_INDEX_STRUCT_PTR((psBase)->psHandleArray, i)
+
+#define        INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->ui32FreeHandBlockCount)
+
+#define INDEX_TO_HANDLE_STRUCT_PTR(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->psHandle + INDEX_TO_SUB_BLOCK_INDEX(i))
+
+#define        HANDLE_TO_HANDLE_STRUCT_PTR(psBase, h) (INDEX_TO_HANDLE_STRUCT_PTR(psBase, HANDLE_TO_INDEX(h)))
+
+#define        HANDLE_PTR_TO_INDEX(psHandle) ((psHandle)->ui32Index)
+#define        HANDLE_PTR_TO_HANDLE(psHandle) INDEX_TO_HANDLE(HANDLE_PTR_TO_INDEX(psHandle))
+
+#define        ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(a) (HANDLE_BLOCK_MASK & (a))
+#define        ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(a) ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE((a) + HANDLE_BLOCK_SIZE - 1)
+
+#define        DEFAULT_MAX_HANDLE              0x7fffffffu
+#define        DEFAULT_MAX_INDEX_PLUS_ONE      ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(DEFAULT_MAX_HANDLE)
+
+#define        HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
+
+#define HANDLE_ARRAY_SIZE(handleCount) DIVIDE_BY_BLOCK_SIZE(ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(handleCount))
+
+#define        SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
+#define        CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
+#define        TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
+
+#define        TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
+
+#define        SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
+#define        CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
+#define        TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
+
+#define        BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define        SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define        SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define        BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define        HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
+
+#ifdef MIN
+#undef MIN
+#endif
+
+#define        MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+struct sHandleList
+{
+       IMG_UINT32 ui32Prev;
+       IMG_UINT32 ui32Next;
+       IMG_HANDLE hParent;
+};
+
+enum ePVRSRVInternalHandleFlag
+{
+       INTERNAL_HANDLE_FLAG_NONE = 0x00,
+       INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
+       INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
+};
+
+struct sHandle
+{
+       
+       PVRSRV_HANDLE_TYPE eType;
+
+       
+       IMG_VOID *pvData;
+
+       
+       IMG_UINT32 ui32NextIndexPlusOne;
+
+       
+       enum ePVRSRVInternalHandleFlag eInternalFlag;
+
+       
+       PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+       
+       IMG_UINT32 ui32Index;
+
+       
+       struct sHandleList sChildren;
+
+       
+       struct sHandleList sSiblings;
+};
+
+struct sHandleIndex
+{
+       
+       struct sHandle *psHandle;
+
+       
+       IMG_HANDLE hBlockAlloc;
+
+       
+       IMG_UINT32 ui32FreeHandBlockCount;
+};
+
+struct _PVRSRV_HANDLE_BASE_
+{
+       
+       IMG_HANDLE hBaseBlockAlloc;
+
+       
+       IMG_HANDLE hArrayBlockAlloc;
+
+       
+       struct sHandleIndex *psHandleArray;
+
+       
+       HASH_TABLE *psHashTab;
+
+       
+       IMG_UINT32 ui32FreeHandCount;
+
+       
+       IMG_UINT32 ui32FirstFreeIndex;
+
+       
+       IMG_UINT32 ui32MaxIndexPlusOne;
+
+       
+       IMG_UINT32 ui32TotalHandCount;
+
+       
+       IMG_UINT32 ui32LastFreeIndexPlusOne;
+
+       
+       IMG_UINT32 ui32HandBatchSize;
+
+       
+       IMG_UINT32 ui32TotalHandCountPreBatch;
+
+       
+       IMG_UINT32 ui32FirstBatchIndexPlusOne;
+
+       
+       IMG_UINT32 ui32BatchHandAllocFailures;
+
+       
+       IMG_BOOL bPurgingEnabled;
+};
+
+enum eHandKey {
+       HAND_KEY_DATA = 0,
+       HAND_KEY_TYPE,
+       HAND_KEY_PARENT,
+       HAND_KEY_LEN                    
+};
+
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+
+typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInit)
+#endif
+static INLINE
+IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
+{
+       psList->ui32Next = ui32Index;
+       psList->ui32Prev = ui32Index;
+       psList->hParent = hParent;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitParentList)
+#endif
+static INLINE
+IMG_VOID InitParentList(struct sHandle *psHandle)
+{
+       IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psHandle);
+
+       HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitChildEntry)
+#endif
+static INLINE
+IMG_VOID InitChildEntry(struct sHandle *psHandle)
+{
+       HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIsEmpty)
+#endif
+static INLINE
+IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
+{
+       IMG_BOOL bIsEmpty;
+
+       bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
+
+#ifdef DEBUG
+       {
+               IMG_BOOL bIsEmpty2;
+
+               bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
+               PVR_ASSERT(bIsEmpty == bIsEmpty2);
+       }
+#endif
+
+       return bIsEmpty;
+}
+
+#ifdef DEBUG
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoChildren)
+#endif
+static INLINE
+IMG_BOOL NoChildren(struct sHandle *psHandle)
+{
+       PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle));
+
+       return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoParent)
+#endif
+static INLINE
+IMG_BOOL NoParent(struct sHandle *psHandle)
+{
+       if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings))
+       {
+               PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
+
+               return IMG_TRUE;
+       }
+       else
+       {
+               PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
+       }
+       return IMG_FALSE;
+}
+#endif 
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentHandle)
+#endif
+static INLINE
+IMG_HANDLE ParentHandle(struct sHandle *psHandle)
+{
+       return psHandle->sSiblings.hParent;
+}
+
+#define        LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
+               ((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInsertBefore)
+#endif
+static INLINE
+IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
+{
+        
+       struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
+
+       PVR_ASSERT(psEntry->hParent == IMG_NULL);
+       PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
+       PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex));
+
+       psEntry->ui32Prev = psIns->ui32Prev;
+       psIns->ui32Prev = ui32EntryIndex;
+       psEntry->ui32Next = ui32InsIndex;
+       psPrevIns->ui32Next = ui32EntryIndex;
+
+       psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(AdoptChild)
+#endif
+static INLINE
+IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
+{
+       IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent);
+
+       PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent));
+
+       HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
+
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListRemove)
+#endif
+static INLINE
+IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
+{
+       if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
+       {
+                
+               struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
+               struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
+
+               
+               PVR_ASSERT(psEntry->hParent != IMG_NULL);
+
+               psPrev->ui32Next = psEntry->ui32Next;
+               psNext->ui32Prev = psEntry->ui32Prev;
+
+               HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
+       }
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(UnlinkFromParent)
+#endif
+static INLINE
+IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+       HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIterate)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead, IMG_SIZE_T uiParentOffset, IMG_SIZE_T uiEntryOffset, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+       IMG_UINT32 ui32Index;
+       IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent);
+
+       PVR_ASSERT(psHead->hParent != IMG_NULL);
+
+       
+       for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
+       {
+               struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
+                
+               struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
+               PVRSRV_ERROR eError;
+
+               PVR_ASSERT(psEntry->hParent == psHead->hParent);
+               
+               ui32Index = psEntry->ui32Next;
+
+               eError = (*pfnIterFunc)(psBase, psHandle);
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(IterateOverChildren)
+#endif
+static INLINE
+PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+        return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(GetHandleStructure)
+#endif
+static INLINE
+PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
+       struct sHandle *psHandle;
+
+       
+       if (!INDEX_IS_VALID(psBase, ui32Index))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
+               return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+       }
+
+       psHandle =  INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
+       if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
+               return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
+       }
+
+       
+       if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
+               return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
+       }
+
+       
+       *ppsHandle = psHandle;
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentIfPrivate)
+#endif
+static INLINE
+IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
+{
+       return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+                       ParentHandle(psHandle) : IMG_NULL;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitKey)
+#endif
+static INLINE
+IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
+       aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
+       aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
+}
+
+static
+PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount)
+{
+       struct sHandleIndex *psOldArray = psBase->psHandleArray;
+       IMG_HANDLE hOldArrayBlockAlloc = psBase->hArrayBlockAlloc;
+       IMG_UINT32 ui32OldCount = psBase->ui32TotalHandCount;
+       struct sHandleIndex *psNewArray = IMG_NULL;
+       IMG_HANDLE hNewArrayBlockAlloc = IMG_NULL;
+       PVRSRV_ERROR eError;
+       PVRSRV_ERROR eReturn = PVRSRV_OK;
+       IMG_UINT32 ui32Index;
+
+       if (ui32NewCount == ui32OldCount)
+       {
+               return PVRSRV_OK;
+       }
+
+       if (ui32NewCount != 0 && !psBase->bPurgingEnabled &&
+                ui32NewCount < ui32OldCount)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
+               ((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
+       {
+               PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0);
+               PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0);
+
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (ui32NewCount != 0)
+       {
+               
+               eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                       HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
+                       (IMG_VOID **)&psNewArray,
+                       &hNewArrayBlockAlloc,
+                       "Memory Area");
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate new handle array (%d)", eError));
+                       eReturn = eError;
+                       goto error;
+               }
+
+               if (ui32OldCount != 0)
+               {
+                       OSMemCopy(psNewArray, psOldArray, HANDLE_ARRAY_SIZE(MIN(ui32NewCount, ui32OldCount)) * sizeof(struct sHandleIndex));
+               }
+       }
+
+       
+       for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
+       {
+               struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index);
+
+               eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                               sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+                               psIndex->psHandle,
+                               psIndex->hBlockAlloc);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
+               }
+       }
+
+       
+       for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+       {
+                
+               struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
+
+               eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                               sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+                               (IMG_VOID **)&psIndex->psHandle,
+                               &psIndex->hBlockAlloc,
+                               "Memory Area");
+               if (eError != PVRSRV_OK)
+               {
+                       psIndex->psHandle = IMG_NULL;
+                       PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate handle structures (%d)", eError));
+                       eReturn = eError;
+               }
+               else
+               {
+                       IMG_UINT32 ui32SubIndex;
+
+                       psIndex->ui32FreeHandBlockCount = HANDLE_BLOCK_SIZE;
+
+                       for(ui32SubIndex = 0; ui32SubIndex < HANDLE_BLOCK_SIZE; ui32SubIndex++)
+                       {
+                               struct sHandle *psHandle = psIndex->psHandle + ui32SubIndex;
+
+
+                               psHandle->ui32Index = ui32SubIndex + ui32Index;
+                               psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+                               psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+                               psHandle->ui32NextIndexPlusOne  = 0;
+                       }
+               }
+       }
+       if (eReturn != PVRSRV_OK)
+       {
+               goto error;
+       }
+
+#ifdef DEBUG_MAX_HANDLE_COUNT
+       
+       if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT));
+               eReturn = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto error;
+       }
+#endif
+
+       if (psOldArray != IMG_NULL)
+       {
+               
+               eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                       HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex),
+                       psOldArray,
+                       hOldArrayBlockAlloc);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free old handle array (%d)", eError));
+               }
+       }
+
+       psBase->psHandleArray = psNewArray;
+       psBase->hArrayBlockAlloc = hNewArrayBlockAlloc;
+       psBase->ui32TotalHandCount = ui32NewCount;
+
+       if (ui32NewCount > ui32OldCount)
+       {
+               
+               PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount)
+
+                
+               psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount);
+
+               
+               if (psBase->ui32FirstFreeIndex == 0)
+               {
+                       PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
+
+                       psBase->ui32FirstFreeIndex = ui32OldCount;
+               }
+               else
+               {
+                       if (!psBase->bPurgingEnabled)
+                       {
+                               PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
+                               PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
+
+                               INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
+                       }
+               }
+
+               if (!psBase->bPurgingEnabled)
+               {
+                       psBase->ui32LastFreeIndexPlusOne = ui32NewCount;
+               }
+       }
+       else
+       {
+               PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled)
+               PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount)
+               PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount)
+
+                
+               psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount);
+
+               if (ui32NewCount == 0)
+               {
+                       psBase->ui32FirstFreeIndex = 0;
+                       psBase->ui32LastFreeIndexPlusOne = 0;
+               }
+       }
+
+       PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount);
+
+       return PVRSRV_OK;
+
+error:
+       PVR_ASSERT(eReturn != PVRSRV_OK);
+
+       if (psNewArray != IMG_NULL)
+       {
+               
+               for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+               {
+                       struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
+                       if (psIndex->psHandle != IMG_NULL)
+                       {
+                               eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+                                               psIndex->psHandle,
+                                               psIndex->hBlockAlloc);
+                               if (eError != PVRSRV_OK)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
+                               }
+                       }
+               }
+
+               
+               eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                       HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
+                       psNewArray,
+                       hNewArrayBlockAlloc);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free new handle array (%d)", eError));
+               }
+       }
+
+       return eReturn;
+}
+
+static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
+{
+       return ReallocHandleArray(psBase, 0);
+}
+
+static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+       HAND_KEY aKey;
+       IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle);
+       PVRSRV_ERROR eError;
+
+       
+       InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
+
+       if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+       {
+               IMG_HANDLE hHandle;
+               hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
+
+               PVR_ASSERT(hHandle != IMG_NULL);
+               PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index));
+               PVR_UNREFERENCED_PARAMETER(hHandle);
+       }
+
+       
+       UnlinkFromParent(psBase, psHandle);
+
+       
+       eError = IterateOverChildren(psBase, psHandle, FreeHandle);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
+               return eError;
+       }
+
+       
+       psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+
+       if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+       {
+                
+        SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
+               
+               return PVRSRV_OK;
+       }
+
+       
+       if (!psBase->bPurgingEnabled)
+       {
+               if (psBase->ui32FreeHandCount == 0)
+               {
+                       PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+                       PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+                       psBase->ui32FirstFreeIndex =  ui32Index;
+               }
+               else
+               {
+                       
+                       PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+                       PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+                       INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne =  ui32Index + 1;
+               }
+
+               PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
+
+               
+               psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+       }
+
+       psBase->ui32FreeHandCount++;
+       INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++;
+
+       PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE);
+
+#ifdef DEBUG
+       {
+               IMG_UINT32 ui32BlockedIndex;
+               IMG_UINT32 ui32FreeHandCount = 0;
+
+               for (ui32BlockedIndex = 0; ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+               {
+                       ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex);
+               }
+
+               PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount);
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+       IMG_UINT32 i;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+       {
+               return eError;
+       }
+
+       for (i = 0; i < psBase->ui32TotalHandCount; i++)
+       {
+               struct sHandle *psHandle;
+
+               psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, i);
+
+               if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
+               {
+                       eError = FreeHandle(psBase, psHandle);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
+                               break;
+                       }
+
+                       
+                       if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+                       {
+                               break;
+                       }
+               }
+       }
+
+       return eError;
+}
+
+static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+       PVRSRV_ERROR eError;
+
+       if (HANDLES_BATCHED(psBase))
+       {
+               PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
+               PVRSRVReleaseHandleBatch(psBase);
+       }
+
+       
+       eError = FreeAllHandles(psBase);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
+               return eError;
+       }
+
+       
+       eError = FreeHandleArray(psBase);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
+               return eError;
+       }
+
+       if (psBase->psHashTab != IMG_NULL)
+       {
+               
+               HASH_Delete(psBase->psHashTab);
+       }
+
+       eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+               sizeof(*psBase),
+               psBase,
+               psBase->hBaseBlockAlloc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(FindHandle)
+#endif
+static INLINE
+IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+       HAND_KEY aKey;
+
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       InitKey(aKey, psBase, pvData, eType, hParent);
+
+       return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+}
+
+static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
+       IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
+;
+
+       PVR_ASSERT(ui32Delta != 0);
+
+       
+       if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
+       {
+               ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
+
+               ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
+
+               if (ui32DeltaAdjusted < ui32Delta)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+       }
+
+       PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
+
+       
+       eError = ReallocHandleArray(psBase, ui32NewTotalHandCount);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
+{
+       PVRSRV_ERROR eError;
+
+       if (ui32Free > psBase->ui32FreeHandCount)
+       {
+               IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
+               eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
+
+                       return eError;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+       IMG_UINT32 ui32NewIndex = DEFAULT_MAX_INDEX_PLUS_ONE;
+       struct sHandle *psNewHandle = IMG_NULL;
+       IMG_HANDLE hHandle;
+       HAND_KEY aKey;
+       PVRSRV_ERROR eError;
+
+       
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+       PVR_ASSERT(psBase != IMG_NULL);
+       PVR_ASSERT(psBase->psHashTab != IMG_NULL);
+
+       if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+       {
+               
+               PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
+       }
+
+       if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
+       {
+                PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
+       }
+
+       
+       eError = EnsureFreeHandles(psBase, 1);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
+               return eError;
+       }
+       PVR_ASSERT(psBase->ui32FreeHandCount != 0)
+
+       if (!psBase->bPurgingEnabled)
+       {
+               
+               ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+               
+               psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
+       }
+       else
+       {
+               IMG_UINT32 ui32BlockedIndex;
+
+               
+               
+               PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);
+
+               for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+               {
+                       struct sHandleIndex *psIndex = BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, ui32BlockedIndex);
+
+                       if (psIndex->ui32FreeHandBlockCount == 0)
+                       {
+                               continue;
+                       }
+
+                       for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
+                       {
+                               psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
+                               if (HANDLE_STRUCT_IS_FREE(psNewHandle))
+                               {
+                                       break;
+                               }
+                       }
+               }
+               psBase->ui32FirstFreeIndex = 0;
+               PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
+       }
+       PVR_ASSERT(psNewHandle != IMG_NULL);
+
+       
+       hHandle = INDEX_TO_HANDLE(ui32NewIndex);
+
+       
+       if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+       {
+               
+               InitKey(aKey, psBase, pvData, eType, hParent);
+
+               
+               if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
+
+                       return PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
+               }
+       }
+
+       psBase->ui32FreeHandCount--;
+
+       PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
+       PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0);
+
+       INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--;
+
+       
+       if (!psBase->bPurgingEnabled)
+       {
+               
+               if (psBase->ui32FreeHandCount == 0)
+               {
+                       PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+                       PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
+
+                       psBase->ui32LastFreeIndexPlusOne = 0;
+                       psBase->ui32FirstFreeIndex = 0;
+               }
+               else
+               {
+                       
+                       psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
+                               ui32NewIndex + 1 :
+                               psNewHandle->ui32NextIndexPlusOne - 1;
+               }
+       }
+
+       
+       PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex);
+
+        
+       psNewHandle->eType = eType;
+       psNewHandle->pvData = pvData;
+       psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+       psNewHandle->eFlag = eFlag;
+
+       InitParentList(psNewHandle);
+#if defined(DEBUG)
+       PVR_ASSERT(NoChildren(psNewHandle));
+#endif
+
+       InitChildEntry(psNewHandle);
+#if defined(DEBUG)
+       PVR_ASSERT(NoParent(psNewHandle));
+#endif
+
+       if (HANDLES_BATCHED(psBase))
+       {
+               
+               psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+
+               psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
+
+                
+               SET_BATCHED_HANDLE(psNewHandle);
+       }
+       else
+       {
+               psNewHandle->ui32NextIndexPlusOne = 0;
+       }
+
+       
+       *phHandle = hHandle;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+       IMG_HANDLE hHandle;
+       PVRSRV_ERROR eError;
+
+       *phHandle = IMG_NULL;
+
+       if (HANDLES_BATCHED(psBase))
+       {
+               
+               psBase->ui32BatchHandAllocFailures++;
+       }
+
+       
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+       {
+               
+               hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
+               if (hHandle != IMG_NULL)
+               {
+                       struct sHandle *psHandle;
+
+                       eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
+                               return eError;
+                       }
+
+                       
+                       if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
+                       {
+                               *phHandle = hHandle;
+                               eError = PVRSRV_OK;
+                               goto exit_ok;
+                       }
+                       return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+               }
+       }
+
+       eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
+
+exit_ok:
+       if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
+       {
+               psBase->ui32BatchHandAllocFailures--;
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+       struct sHandle *psPHand;
+       struct sHandle *psCHand;
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hParentKey;
+       IMG_HANDLE hHandle;
+
+       *phHandle = IMG_NULL;
+
+       if (HANDLES_BATCHED(psBase))
+       {
+               
+               psBase->ui32BatchHandAllocFailures++;
+       }
+
+       
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+                       hParent : IMG_NULL;
+
+       
+       eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+       {
+               
+               hHandle = FindHandle(psBase, pvData, eType, hParentKey);
+               if (hHandle != IMG_NULL)
+               {
+                       struct sHandle *psCHandle;
+                       PVRSRV_ERROR eErr;
+
+                       eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
+                       if (eErr != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
+                               return eErr;
+                       }
+
+                       PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent);
+
+                       
+                       if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
+                       {
+                               *phHandle = hHandle;
+                               goto exit_ok;
+                       }
+                       return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+               }
+       }
+
+       eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       
+       psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent);
+
+       psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle);
+
+       AdoptChild(psBase, psPHand, psCHand);
+
+       *phHandle = hHandle;
+
+exit_ok:
+       if (HANDLES_BATCHED(psBase))
+       {
+               psBase->ui32BatchHandAllocFailures--;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+       IMG_HANDLE hHandle;
+
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       
+       hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
+       if (hHandle == IMG_NULL)
+       {
+               return PVRSRV_ERROR_HANDLE_NOT_FOUND;
+       }
+
+       *phHandle = hHandle;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+       struct sHandle *psHandle;
+       PVRSRV_ERROR eError;
+
+       eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
+               return eError;
+       }
+
+       *ppvData = psHandle->pvData;
+       *peType = psHandle->eType;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       struct sHandle *psHandle;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
+               return eError;
+       }
+
+       *ppvData = psHandle->pvData;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+       struct sHandle *psPHand;
+       struct sHandle *psCHand;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
+               return eError;
+       }
+
+       
+       for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
+       {
+               eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
+                       return PVRSRV_ERROR_INVALID_SUBHANDLE;
+               }
+       }
+
+       *ppvData = psCHand->pvData;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       struct sHandle *psHandle;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
+               return eError;
+       }
+
+       *phParent = ParentHandle(psHandle);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       struct sHandle *psHandle;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
+               return eError;
+       }
+
+       *ppvData = psHandle->pvData;
+
+       eError = FreeHandle(psBase, psHandle);
+
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       struct sHandle *psHandle;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
+               return eError;
+       }
+
+       eError = FreeHandle(psBase, psHandle);
+
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+       PVRSRV_ERROR eError;
+
+       if (HANDLES_BATCHED(psBase))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
+               return  PVRSRV_ERROR_HANDLE_BATCH_IN_USE;
+       }
+
+       if (ui32BatchSize == 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
+               return  PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = EnsureFreeHandles(psBase, ui32BatchSize);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
+               return eError;
+       }
+
+       psBase->ui32HandBatchSize = ui32BatchSize;
+
+       
+       psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
+
+       PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
+
+       PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
+
+       PVR_ASSERT(HANDLES_BATCHED(psBase));
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
+{
+
+       IMG_UINT32 ui32IndexPlusOne;
+       IMG_BOOL bCommitBatch = bCommit;
+
+       if (!HANDLES_BATCHED(psBase))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       }
+
+       if (psBase->ui32BatchHandAllocFailures != 0)
+       {
+               if (bCommit)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
+               }
+               bCommitBatch = IMG_FALSE;
+       }
+       
+       PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
+
+       ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+       while(ui32IndexPlusOne != 0)
+       {
+               struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1);
+               IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
+               PVR_ASSERT(BATCHED_HANDLE(psHandle));
+
+               psHandle->ui32NextIndexPlusOne = 0;
+
+               if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+               {
+                       PVRSRV_ERROR eError;
+
+                       
+                       if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+                       {
+                                
+                               SET_UNBATCHED_HANDLE(psHandle);  
+                       }
+
+                       eError = FreeHandle(psBase, psHandle);
+                       if (eError != PVRSRV_OK)
+                       {
+                                PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
+                       }
+                       PVR_ASSERT(eError == PVRSRV_OK);
+               }
+               else
+               {
+                        
+                       SET_UNBATCHED_HANDLE(psHandle);
+               }
+
+               ui32IndexPlusOne = ui32NextIndexPlusOne;
+       }
+
+#ifdef DEBUG
+       if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
+       {
+               IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
+
+               PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch);
+
+               PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small.  Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize,  psBase->ui32HandBatchSize + ui32Delta));
+
+       }
+#endif
+
+       psBase->ui32HandBatchSize = 0;
+       psBase->ui32FirstBatchIndexPlusOne = 0;
+       psBase->ui32TotalHandCountPreBatch = 0;
+       psBase->ui32BatchHandAllocFailures = 0;
+
+       if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
+       {
+               PVR_ASSERT(!bCommitBatch);
+
+               return PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+       return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
+}
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+       (IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
+}
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+       IMG_UINT32 ui32MaxHandleRounded;
+
+       if (HANDLES_BATCHED(psBase))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       if (ui32MaxHandle  == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
+
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       if (psBase->ui32TotalHandCount != 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated"));
+
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle);
+
+       
+       if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne)
+       {
+               psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded;
+       }
+
+       PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0);
+       PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE);
+       PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0);
+
+       return PVRSRV_OK;
+}
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+       return psBase->ui32MaxIndexPlusOne;
+}
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+       if (psBase->bPurgingEnabled)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
+               return PVRSRV_OK;
+       }
+
+       
+       if (psBase->ui32TotalHandCount != 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psBase->bPurgingEnabled = IMG_TRUE;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+       IMG_UINT32 ui32BlockIndex;
+       IMG_UINT32 ui32NewHandCount;
+
+       if (!psBase->bPurgingEnabled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
+               return PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       if (HANDLES_BATCHED(psBase))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0);
+
+       for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
+       {
+               if (psBase->psHandleArray[ui32BlockIndex - 1].ui32FreeHandBlockCount != HANDLE_BLOCK_SIZE)
+               {
+                       break;
+               }
+       }
+       ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
+
+       
+       if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
+       {
+               PVRSRV_ERROR eError;
+
+               
+
+               eError = ReallocHandleArray(psBase, ui32NewHandCount);
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+       PVRSRV_HANDLE_BASE *psBase;
+       IMG_HANDLE hBlockAlloc;
+       PVRSRV_ERROR eError;
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+               sizeof(*psBase),
+               (IMG_PVOID *)&psBase,
+               &hBlockAlloc,
+               "Handle Base");
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
+               return eError;
+       }
+       OSMemSet(psBase, 0, sizeof(*psBase));
+
+       
+       psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
+       if (psBase->psHashTab == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
+               (IMG_VOID)PVRSRVFreeHandleBase(psBase);
+               return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+       }
+
+       psBase->hBaseBlockAlloc = hBlockAlloc;
+
+       psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
+
+       *ppsBase = psBase;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psBase != gpsKernelHandleBase);
+
+       eError = FreeHandleBase(psBase);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
+
+       eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
+               goto error;
+       }
+
+       eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
+               goto error;
+       }
+
+       return PVRSRV_OK;
+error:
+       (IMG_VOID) PVRSRVHandleDeInit();
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (gpsKernelHandleBase != IMG_NULL)
+       {
+               eError = FreeHandleBase(gpsKernelHandleBase);
+               if (eError == PVRSRV_OK)
+               {
+                       gpsKernelHandleBase = IMG_NULL;
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));
+               }
+       }
+
+       return eError;
+}
+#else
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/hash.c b/drivers/staging/mrst/pvr/services4/srvkm/common/hash.c
new file mode 100644 (file)
index 0000000..32b0779
--- /dev/null
@@ -0,0 +1,477 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "pvr_debug.h"
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "hash.h"
+#include "osfunc.h"
+
+#define PRIVATE_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define        KEY_TO_INDEX(pHash, key, uSize) \
+       ((pHash)->pfnHashFunc((pHash)->uKeySize, (key), (uSize)) % (uSize))
+
+#define        KEY_COMPARE(pHash, pKey1, pKey2) \
+       ((pHash)->pfnKeyComp((pHash)->uKeySize, (pKey1), (pKey2)))
+
+struct _BUCKET_
+{
+       
+       struct _BUCKET_ *pNext;
+
+       
+       IMG_UINTPTR_T v;
+
+       
+       IMG_UINTPTR_T k[];               
+};
+typedef struct _BUCKET_ BUCKET;
+
+struct _HASH_TABLE_
+{
+       
+       BUCKET **ppBucketTable;
+
+       
+       IMG_UINT32 uSize;
+
+       
+       IMG_UINT32 uCount;
+
+       
+       IMG_UINT32 uMinimumSize;
+
+       
+       IMG_UINT32 uKeySize;
+
+       
+       HASH_FUNC *pfnHashFunc;
+
+       
+       HASH_KEY_COMP *pfnKeyComp;
+};
+
+IMG_UINT32
+HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
+{
+       IMG_UINTPTR_T *p = (IMG_UINTPTR_T *)pKey;
+       IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+       IMG_UINT32 ui;
+       IMG_UINT32 uHashKey = 0;
+
+       PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+       PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+       for (ui = 0; ui < uKeyLen; ui++)
+       {
+               IMG_UINT32 uHashPart = (IMG_UINT32)*p++;
+
+               uHashPart += (uHashPart << 12);
+               uHashPart ^= (uHashPart >> 22);
+               uHashPart += (uHashPart << 4);
+               uHashPart ^= (uHashPart >> 9);
+               uHashPart += (uHashPart << 10);
+               uHashPart ^= (uHashPart >> 2);
+               uHashPart += (uHashPart << 7);
+               uHashPart ^= (uHashPart >> 12);
+
+               uHashKey += uHashPart;
+       }
+
+       return uHashKey;
+}
+
+IMG_BOOL
+HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
+{
+       IMG_UINTPTR_T *p1 = (IMG_UINTPTR_T *)pKey1;
+       IMG_UINTPTR_T *p2 = (IMG_UINTPTR_T *)pKey2;
+       IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+       IMG_UINT32 ui;
+
+       PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+       for (ui = 0; ui < uKeyLen; ui++)
+       {
+               if (*p1++ != *p2++)
+                       return IMG_FALSE;
+       }
+
+       return IMG_TRUE;
+}
+
+static PVRSRV_ERROR
+_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
+{
+       IMG_UINT32 uIndex;
+
+       PVR_ASSERT (pBucket != IMG_NULL);
+       PVR_ASSERT (ppBucketTable != IMG_NULL);
+       PVR_ASSERT (uSize != 0);
+
+       if ((pBucket == IMG_NULL) || (ppBucketTable == IMG_NULL) || (uSize == 0))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "_ChainInsert: invalid parameter"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);         
+       pBucket->pNext = ppBucketTable[uIndex];
+       ppBucketTable[uIndex] = pBucket;
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_Rehash (HASH_TABLE *pHash,
+        BUCKET **ppOldTable, IMG_UINT32 uOldSize,
+         BUCKET **ppNewTable, IMG_UINT32 uNewSize)
+{
+       IMG_UINT32 uIndex;
+       for (uIndex=0; uIndex< uOldSize; uIndex++)
+    {
+               BUCKET *pBucket;
+               pBucket = ppOldTable[uIndex];
+               while (pBucket != IMG_NULL)
+               {
+                       PVRSRV_ERROR eError;
+                       BUCKET *pNextBucket = pBucket->pNext;
+                       eError = _ChainInsert (pHash, pBucket, ppNewTable, uNewSize);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "_Rehash: call to _ChainInsert failed"));
+                               return eError;
+                       }
+                       pBucket = pNextBucket;
+               }
+    }
+       return PVRSRV_OK;
+}
+
+static IMG_BOOL
+_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
+{
+       if (uNewSize != pHash->uSize)
+    {
+               BUCKET **ppNewTable;
+        IMG_UINT32 uIndex;
+
+               PVR_DPF ((PVR_DBG_MESSAGE,
+                  "HASH_Resize: oldsize=0x%x  newsize=0x%x  count=0x%x",
+                               pHash->uSize, uNewSize, pHash->uCount));
+
+               OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                      sizeof (BUCKET *) * uNewSize,
+                      (IMG_PVOID*)&ppNewTable, IMG_NULL,
+                                         "Hash Table Buckets");
+               if (ppNewTable == IMG_NULL)
+            return IMG_FALSE;
+
+        for (uIndex=0; uIndex<uNewSize; uIndex++)
+            ppNewTable[uIndex] = IMG_NULL;
+
+        if (_Rehash (pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable, uNewSize) != PVRSRV_OK)
+               {
+                       return IMG_FALSE;
+               }
+
+        OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+        
+        pHash->ppBucketTable = ppNewTable;
+        pHash->uSize = uNewSize;
+    }
+    return IMG_TRUE;
+}
+
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
+{
+       HASH_TABLE *pHash;
+       IMG_UINT32 uIndex;
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x", uInitialLen));
+
+       if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                                       sizeof(HASH_TABLE),
+                                       (IMG_VOID **)&pHash, IMG_NULL,
+                                       "Hash Table") != PVRSRV_OK)
+       {
+               return IMG_NULL;
+       }
+
+       pHash->uCount = 0;
+       pHash->uSize = uInitialLen;
+       pHash->uMinimumSize = uInitialLen;
+       pHash->uKeySize = uKeySize;
+       pHash->pfnHashFunc = pfnHashFunc;
+       pHash->pfnKeyComp = pfnKeyComp;
+
+       OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                  sizeof (BUCKET *) * pHash->uSize,
+                  (IMG_PVOID*)&pHash->ppBucketTable, IMG_NULL,
+                                 "Hash Table Buckets");
+
+       if (pHash->ppBucketTable == IMG_NULL)
+    {
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+               
+               return IMG_NULL;
+    }
+
+       for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+               pHash->ppBucketTable[uIndex] = IMG_NULL;
+       return pHash;
+}
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
+{
+       return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
+               &HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+IMG_VOID
+HASH_Delete (HASH_TABLE *pHash)
+{
+       if (pHash != IMG_NULL)
+    {
+               PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Delete"));
+
+               PVR_ASSERT (pHash->uCount==0);
+               if(pHash->uCount != 0)
+               {
+                       PVR_DPF ((PVR_DBG_ERROR, "HASH_Delete: leak detected in hash table!"));
+                       PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+               }
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+               pHash->ppBucketTable = IMG_NULL;
+               OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+               
+    }
+}
+
+IMG_BOOL
+HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
+{
+       BUCKET *pBucket;
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Insert_Extended: Hash=0x%08x, pKey=0x%08x, v=0x%x",
+              (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+
+       PVR_ASSERT (pHash != IMG_NULL);
+
+       if (pHash == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "HASH_Insert_Extended: invalid parameter"));
+               return IMG_FALSE;
+       }
+
+       if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                                       sizeof(BUCKET) + pHash->uKeySize,
+                                       (IMG_VOID **)&pBucket, IMG_NULL,
+                                       "Hash Table entry") != PVRSRV_OK)
+       {
+               return IMG_FALSE;
+       }
+
+       pBucket->v = v;
+        
+       OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+       if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
+       {
+               return IMG_FALSE;
+       }
+
+       pHash->uCount++;
+
+       
+       if (pHash->uCount << 1 > pHash->uSize)
+    {
+        
+
+        _Resize (pHash, pHash->uSize << 1);
+    }
+
+
+       return IMG_TRUE;
+}
+
+IMG_BOOL
+HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+       PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Insert: Hash=0x%x, k=0x%x, v=0x%x",
+              (IMG_UINTPTR_T)pHash, k, v));
+
+       return HASH_Insert_Extended(pHash, &k, v);
+}
+
+IMG_UINTPTR_T
+HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+       BUCKET **ppBucket;
+       IMG_UINT32 uIndex;
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x",
+                       (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+
+       PVR_ASSERT (pHash != IMG_NULL);
+
+       if (pHash == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "HASH_Remove_Extended: Null hash table"));
+               return 0;
+       }
+
+       uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+       for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+       {
+                
+               if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+               {
+                       BUCKET *pBucket = *ppBucket;
+                       IMG_UINTPTR_T v = pBucket->v;
+                       (*ppBucket) = pBucket->pNext;
+
+                       OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET) + pHash->uKeySize, pBucket, IMG_NULL);
+                       
+
+                       pHash->uCount--;
+
+                       
+                       if (pHash->uSize > (pHash->uCount << 2) &&
+                pHash->uSize > pHash->uMinimumSize)
+            {
+                
+
+                               _Resize (pHash,
+                         PRIVATE_MAX (pHash->uSize >> 1,
+                                      pHash->uMinimumSize));
+            }
+
+                       PVR_DPF ((PVR_DBG_MESSAGE,
+                      "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x = 0x%x",
+                      (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+                       return v;
+               }
+       }
+       PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x = 0x0 !!!!",
+              (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+       return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+       PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove: Hash=0x%x, k=0x%x",
+                       (IMG_UINTPTR_T)pHash, k));
+
+       return HASH_Remove_Extended(pHash, &k);
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+       BUCKET **ppBucket;
+       IMG_UINT32 uIndex;
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve_Extended: Hash=0x%x, pKey=0x%x",
+                       (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+
+       PVR_ASSERT (pHash != IMG_NULL);
+
+       if (pHash == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "HASH_Retrieve_Extended: Null hash table"));
+               return 0;
+       }
+
+       uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+       for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+       {
+                
+               if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+               {
+                       BUCKET *pBucket = *ppBucket;
+                       IMG_UINTPTR_T v = pBucket->v;
+
+                       PVR_DPF ((PVR_DBG_MESSAGE,
+                      "HASH_Retrieve: Hash=0x%x, pKey=0x%x = 0x%x",
+                      (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+                       return v;
+               }
+       }
+       PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Retrieve: Hash=0x%x, pKey=0x%x = 0x0 !!!!",
+              (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+       return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+       PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=0x%x, k=0x%x",
+                       (IMG_UINTPTR_T)pHash, k));
+       return HASH_Retrieve_Extended(pHash, &k);
+}
+
+#ifdef HASH_TRACE
+IMG_VOID
+HASH_Dump (HASH_TABLE *pHash)
+{
+       IMG_UINT32 uIndex;
+       IMG_UINT32 uMaxLength=0;
+       IMG_UINT32 uEmptyCount=0;
+
+       PVR_ASSERT (pHash != IMG_NULL);
+       for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+       {
+               BUCKET *pBucket;
+               IMG_UINT32 uLength = 0;
+               if (pHash->ppBucketTable[uIndex] == IMG_NULL)
+               {
+                       uEmptyCount++;
+               }
+               for (pBucket=pHash->ppBucketTable[uIndex];
+                               pBucket != IMG_NULL;
+                               pBucket = pBucket->pNext)
+               {
+                       uLength++;
+               }
+               uMaxLength = PRIVATE_MAX (uMaxLength, uLength);
+       }
+
+       PVR_TRACE(("hash table: uMinimumSize=%d  size=%d  count=%d",
+                       pHash->uMinimumSize, pHash->uSize, pHash->uCount));
+       PVR_TRACE(("  empty=%d  max=%d", uEmptyCount, uMaxLength));
+}
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/lists.c b/drivers/staging/mrst/pvr/services4/srvkm/common/lists.c
new file mode 100644 (file)
index 0000000..3fc8c5a
--- /dev/null
@@ -0,0 +1,108 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "lists.h"
+#include "services_headers.h"
+
+IMPLEMENT_LIST_ANY_VA(BM_HEAP)
+IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH_VA(BM_HEAP)
+IMPLEMENT_LIST_REMOVE(BM_HEAP)
+IMPLEMENT_LIST_INSERT(BM_HEAP)
+IMPLEMENT_LIST_FIND(BM_HEAP)
+
+IMPLEMENT_LIST_ANY_VA(BM_CONTEXT)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(BM_CONTEXT)
+IMPLEMENT_LIST_REMOVE(BM_CONTEXT)
+IMPLEMENT_LIST_INSERT(BM_CONTEXT)
+IMPLEMENT_LIST_FIND(BM_CONTEXT)
+
+IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FIND(PVRSRV_DEVICE_NODE)
+
+IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+
+#if defined(PERPROC_LIST)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_PER_PROCESS_DATA);
+IMPLEMENT_LIST_INSERT(PVRSRV_PER_PROCESS_DATA);
+IMPLEMENT_LIST_REMOVE(PVRSRV_PER_PROCESS_DATA);
+#endif
+
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
+{
+       IMG_UINT32 ui32DevIndex;
+       IMG_BOOL bIgnoreClass;
+       PVRSRV_DEVICE_CLASS eDevClass;
+
+       ui32DevIndex = va_arg(va, IMG_UINT32);
+       bIgnoreClass = va_arg(va, IMG_BOOL);
+       if (!bIgnoreClass)
+       {
+               eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+       }
+       else
+       {
+
+
+               eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
+       }
+
+       if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
+               psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
+       {
+               return psDeviceNode;
+       }
+       return IMG_NULL;
+}
+
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
+{
+       IMG_UINT32 ui32DeviceIndex;
+
+       ui32DeviceIndex = va_arg(va, IMG_UINT32);
+
+       if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex)
+       {
+               return psPowerDev;
+       }
+       else
+       {
+               return IMG_NULL;
+       }
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/mem.c b/drivers/staging/mrst/pvr/services4/srvkm/common/mem.c
new file mode 100644 (file)
index 0000000..005a12c
--- /dev/null
@@ -0,0 +1,151 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pvr_bridge_km.h"
+
+
+static PVRSRV_ERROR
+FreeSharedSysMemCallBack(IMG_PVOID     pvParam,
+                                                IMG_UINT32     ui32Param)
+{
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       OSFreePages(psKernelMemInfo->ui32Flags,
+                               psKernelMemInfo->ui32AllocSize,
+                               psKernelMemInfo->pvLinAddrKM,
+                               psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         sizeof(PVRSRV_KERNEL_MEM_INFO),
+                         psKernelMemInfo,
+                         IMG_NULL);
+
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA   *psPerProc,
+                                                        IMG_UINT32                                     ui32Flags,
+                                                        IMG_SIZE_T                             ui32Size,
+                                                        PVRSRV_KERNEL_MEM_INFO         **ppsKernelMemInfo)
+{
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                 (IMG_VOID **)&psKernelMemInfo, IMG_NULL,
+                                 "Kernel Memory Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo));
+
+       ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+       ui32Flags |= PVRSRV_HAP_MULTI_PROCESS;
+       psKernelMemInfo->ui32Flags = ui32Flags;
+       psKernelMemInfo->ui32AllocSize = ui32Size;
+
+       if(OSAllocPages(psKernelMemInfo->ui32Flags,
+                                       psKernelMemInfo->ui32AllocSize,
+                                       HOST_PAGESIZE(),
+                                       &psKernelMemInfo->pvLinAddrKM,
+                                       &psKernelMemInfo->sMemBlk.hOSMemHandle)
+               != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                 psKernelMemInfo,
+                                 0);
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+
+       psKernelMemInfo->sMemBlk.hResItem =
+                               ResManRegisterRes(psPerProc->hResManContext,
+                                                                 RESMAN_TYPE_SHARED_MEM_INFO,
+                                                                 psKernelMemInfo,
+                                                                 0,
+                                                                 &FreeSharedSysMemCallBack);
+
+       *ppsKernelMemInfo = psKernelMemInfo;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+       PVRSRV_ERROR eError;
+
+       if(psKernelMemInfo->sMemBlk.hResItem)
+       {
+               eError = ResManFreeResByPtr(psKernelMemInfo->sMemBlk.hResItem);
+       }
+       else
+       {
+               eError = FreeSharedSysMemCallBack(psKernelMemInfo, 0);
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if(!psKernelMemInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if(psKernelMemInfo->sMemBlk.hResItem)
+       {
+               eError = ResManDissociateRes(psKernelMemInfo->sMemBlk.hResItem, IMG_NULL);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVDissociateMemFromResmanKM: ResManDissociateRes failed"));
+                       PVR_DBG_BREAK;
+                       return eError;
+               }
+
+               psKernelMemInfo->sMemBlk.hResItem = IMG_NULL;
+       }
+
+       return eError;
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/mem_debug.c b/drivers/staging/mrst/pvr/services4/srvkm/common/mem_debug.c
new file mode 100644 (file)
index 0000000..eeb86ae
--- /dev/null
@@ -0,0 +1,250 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef MEM_DEBUG_C
+#define MEM_DEBUG_C
+
+#if defined(PVRSRV_DEBUG_OS_MEMORY)
+
+#include "img_types.h"
+#include "services_headers.h"
+
+#if defined (__cplusplus)
+extern "C"
+{
+#endif
+
+#define STOP_ON_ERROR 0
+
+
+
+
+
+
+
+
+
+       IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
+       {
+               IMG_UINT8 *pui8Addr;
+               for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++)
+               {
+                       if (*pui8Addr != ui8Pattern)
+                       {
+                               return IMG_FALSE;
+                       }
+               }
+               return IMG_TRUE;
+       }
+
+
+
+       IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
+       {
+               OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+               if (pvCpuVAddr == IMG_NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
+                                        " - referenced %s:%d - allocated %s:%d",
+                                        pvCpuVAddr,
+                                        pszFileName, uLine,
+                                        psInfo->sFileName, psInfo->uLineNo));
+                       while (STOP_ON_ERROR);
+               }
+
+
+               if (((IMG_UINT32)pvCpuVAddr&3) != 0)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment"
+                                        " - referenced %s:%d - allocated %s:%d",
+                                        pvCpuVAddr,
+                                        pszFileName, uLine,
+                                        psInfo->sFileName, psInfo->uLineNo));
+                       while (STOP_ON_ERROR);
+               }
+
+
+               if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten"
+                                        " - referenced %s:%d - allocated %s:%d",
+                                        pvCpuVAddr,
+                                        pszFileName, uLine,
+                                        psInfo->sFileName, psInfo->uLineNo));
+                       while (STOP_ON_ERROR);
+               }
+
+
+               if (uSize != psInfo->uSize)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
+                                        " - referenced %s:%d - allocated %s:%d",
+                                        pvCpuVAddr, uSize, psInfo->uSize,
+                                        pszFileName, uLine,
+                                        psInfo->sFileName, psInfo->uLineNo));
+                       while (STOP_ON_ERROR);
+               }
+
+
+               if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
+                                        " - referenced %s:%d - allocated %s:%d",
+                                        pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck,
+                                        pszFileName, uLine,
+                                        psInfo->sFileName, psInfo->uLineNo));
+                       while (STOP_ON_ERROR);
+               }
+               else
+               {
+
+                       uSize = psInfo->uSize;
+               }
+
+
+               if (uSize)
+               {
+                       if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region after overwritten"
+                                                " - referenced from %s:%d - allocated from %s:%d",
+                                                pvCpuVAddr,
+                                                pszFileName, uLine,
+                                                psInfo->sFileName, psInfo->uLineNo));
+                       }
+               }
+
+
+               if (psInfo->eValid != isAllocated)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)"
+                                        " - referenced %s:%d - freed %s:%d",
+                                        pvCpuVAddr, psInfo->eValid == isFree,
+                                        pszFileName, uLine,
+                                        psInfo->sFileName, psInfo->uLineNo));
+                       while (STOP_ON_ERROR);
+               }
+       }
+
+       IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc)
+       {
+               IMG_SIZE_T i = 0;
+
+               for (; i < 128; i++)
+               {
+                       *pDest = *pSrc;
+                       if (*pSrc == '\0') break;
+                       pDest++;
+                       pSrc++;
+               }
+       }
+
+       PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+                                                                                 IMG_UINT32 ui32Size,
+                                                                                 IMG_PVOID *ppvCpuVAddr,
+                                                                                 IMG_HANDLE *phBlockAlloc,
+                                                                                 IMG_CHAR *pszFilename,
+                                                                                 IMG_UINT32 ui32Line)
+       {
+               OSMEM_DEBUG_INFO *psInfo;
+
+               PVRSRV_ERROR eError;
+
+               eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags,
+                                ui32Size + TEST_BUFFER_PADDING,
+                                ppvCpuVAddr,
+                                phBlockAlloc,
+                                pszFilename,
+                                ui32Line);
+
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+
+
+               OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
+               OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
+
+
+               psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
+
+               OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
+               debug_strcpy(psInfo->sFileName, pszFilename);
+               psInfo->uLineNo = ui32Line;
+               psInfo->eValid = isAllocated;
+               psInfo->uSize = ui32Size;
+               psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
+
+
+               *ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+
+               PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
+#endif
+
+               return PVRSRV_OK;
+       }
+
+       PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+                                                                                IMG_UINT32 ui32Size,
+                                                                                IMG_PVOID pvCpuVAddr,
+                                                                                IMG_HANDLE hBlockAlloc,
+                                                                                IMG_CHAR *pszFilename,
+                                                                                IMG_UINT32 ui32Line)
+       {
+               OSMEM_DEBUG_INFO *psInfo;
+
+
+               OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
+
+
+               OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+
+
+               psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+               psInfo->uSize = 0;
+               psInfo->uSizeParityCheck = 0;
+               psInfo->eValid = isFree;
+               psInfo->uLineNo = ui32Line;
+               debug_strcpy(psInfo->sFileName, pszFilename);
+
+               return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line);
+       }
+
+#if defined (__cplusplus)
+
+}
+#endif
+
+#endif
+
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/metrics.c b/drivers/staging/mrst/pvr/services4/srvkm/common/metrics.c
new file mode 100644 (file)
index 0000000..216696e
--- /dev/null
@@ -0,0 +1,160 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "metrics.h"
+
+#if defined(SUPPORT_VGX)
+#include "vgxapi_km.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgxapi_km.h"
+#endif
+
+#if defined(DEBUG) || defined(TIMING)
+
+static volatile IMG_UINT32 *pui32TimerRegister = 0;
+
+#define PVRSRV_TIMER_TOTAL_IN_TICKS(X) asTimers[X].ui32Total
+#define PVRSRV_TIMER_TOTAL_IN_MS(X)            ((1000*asTimers[X].ui32Total)/ui32TicksPerMS)
+#define PVRSRV_TIMER_COUNT(X)                  asTimers[X].ui32Count
+
+
+Temporal_Data asTimers[PVRSRV_NUM_TIMERS];
+
+
+IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
+{
+       if (!pui32TimerRegister)
+       {
+               static IMG_BOOL bFirstTime = IMG_TRUE;
+
+               if (bFirstTime)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVTimeNow: No timer register set up"));
+
+                       bFirstTime = IMG_FALSE;
+               }
+
+               return 0;
+       }
+
+#if defined(__sh__)
+
+       return (0xffffffff-*pui32TimerRegister);
+
+#else
+
+       return 0;
+
+#endif
+}
+
+
+static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
+{
+       IMG_UINT32 ui32Time1, ui32Time2;
+
+       ui32Time1 = PVRSRVTimeNow();
+
+       OSWaitus(1000000);
+
+       ui32Time2 = PVRSRVTimeNow();
+
+       PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetCPUFreq: timer frequency = %d Hz", ui32Time2 - ui32Time1));
+
+       return (ui32Time2 - ui32Time1);
+}
+
+
+IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
+{
+       IMG_UINT32 ui32Loop;
+
+       PVR_UNREFERENCED_PARAMETER(pvDevInfo);
+
+       for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+       {
+               asTimers[ui32Loop].ui32Total = 0;
+               asTimers[ui32Loop].ui32Count = 0;
+       }
+
+
+       #if defined(__sh__)
+
+
+
+
+
+               *TCR_2 = TIMER_DIVISOR;
+
+
+               *TCOR_2 = *TCNT_2 = (IMG_UINT)0xffffffff;
+
+
+               *TST_REG |= (IMG_UINT8)0x04;
+
+               pui32TimerRegister = (IMG_UINT32 *)TCNT_2;
+
+       #else
+
+               pui32TimerRegister = 0;
+
+       #endif
+
+}
+
+
+IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
+{
+       IMG_UINT32 ui32TicksPerMS, ui32Loop;
+
+       ui32TicksPerMS = PVRSRVGetCPUFreq();
+
+       if (!ui32TicksPerMS)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVOutputMetricTotals: Failed to get CPU Freq"));
+               return;
+       }
+
+       for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+       {
+               if (asTimers[ui32Loop].ui32Count & 0x80000000L)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,"PVRSRVOutputMetricTotals: Timer %u is still ON", ui32Loop));
+               }
+       }
+#if 0
+
+       PVR_DPF((PVR_DBG_ERROR," Timer(%u): Total = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_TICKS(PVRSRV_TIMER_EXAMPLE_1)));
+       PVR_DPF((PVR_DBG_ERROR," Timer(%u): Time = %ums",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_MS(PVRSRV_TIMER_EXAMPLE_1)));
+       PVR_DPF((PVR_DBG_ERROR," Timer(%u): Count = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_COUNT(PVRSRV_TIMER_EXAMPLE_1)));
+#endif
+}
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/osfunc_common.c b/drivers/staging/mrst/pvr/services4/srvkm/common/osfunc_common.c
new file mode 100644 (file)
index 0000000..25ac667
--- /dev/null
@@ -0,0 +1,31 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "osfunc.h"
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/pdump_common.c b/drivers/staging/mrst/pvr/services4/srvkm/common/pdump_common.c
new file mode 100644 (file)
index 0000000..3df0739
--- /dev/null
@@ -0,0 +1,2355 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if defined(PDUMP)
+#include <stdarg.h>
+
+#include "services_headers.h"
+#if defined(SUPPORT_SGX)
+#include "sgxdefs.h"
+#endif 
+#include "perproc.h"
+
+#include "pdump_km.h"
+#include "pdump_int.h"
+
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024U)
+#endif
+
+#if 1
+#define PDUMP_DBG(a)   PDumpOSDebugPrintf (a)
+#else
+#define PDUMP_DBG(a)
+#endif
+
+#define PDUMP_DATAMASTER_PIXEL         (1)
+#define PDUMP_DATAMASTER_EDM           (3)
+
+#define        PTR_PLUS(t, p, x) ((t)(((IMG_CHAR *)(p)) + (x)))
+#define        VPTR_PLUS(p, x) PTR_PLUS(IMG_VOID *, p, x)
+#define        VPTR_INC(p, x) ((p) = VPTR_PLUS(p, x))
+#define MAX_PDUMP_MMU_CONTEXTS (32)
+static IMG_VOID *gpvTempBuffer = IMG_NULL;
+static IMG_HANDLE ghTempBufferBlockAlloc;
+static IMG_UINT16 gui16MMUContextUsage = 0;
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+IMG_UINT32 g_ui32EveryLineCounter = 1U;
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(_PDumpIsPersistent)
+#endif
+static INLINE
+IMG_BOOL _PDumpIsPersistent(IMG_VOID)
+{
+       PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+       if(psPerProc == IMG_NULL)
+       {
+               
+               return IMG_FALSE;
+       }
+       return psPerProc->bPDumpPersistent;
+}
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+static INLINE
+IMG_BOOL _PDumpIsProcessActive(IMG_VOID)
+{
+       PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+       if(psPerProc == IMG_NULL)
+       {
+
+               return IMG_TRUE;
+       }
+       return psPerProc->bPDumpActive;
+}
+#endif
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+static INLINE
+IMG_UINT32 _PDumpGetPID(IMG_VOID)
+{
+       PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+       if(psPerProc == IMG_NULL)
+       {
+               
+               return 0;
+       }
+       return psPerProc->ui32PID;
+}
+#endif
+
+static IMG_VOID *GetTempBuffer(IMG_VOID)
+{
+       
+       if (gpvTempBuffer == IMG_NULL)
+       {
+               PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                         PDUMP_TEMP_BUFFER_SIZE,
+                                         &gpvTempBuffer,
+                                         &ghTempBufferBlockAlloc,
+                                         "PDUMP Temporary Buffer");
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "GetTempBuffer: OSAllocMem failed: %d", eError));
+               }
+       }
+
+       return gpvTempBuffer;
+}
+
+static IMG_VOID FreeTempBuffer(IMG_VOID)
+{
+
+       if (gpvTempBuffer != IMG_NULL)
+       {
+               PVRSRV_ERROR eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                         PDUMP_TEMP_BUFFER_SIZE,
+                                         gpvTempBuffer,
+                                         ghTempBufferBlockAlloc);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "FreeTempBuffer: OSFreeMem failed: %d", eError));
+               }
+               else
+               {
+                       gpvTempBuffer = IMG_NULL;
+               }
+       }
+}
+
+IMG_VOID PDumpInitCommon(IMG_VOID)
+{
+       
+       (IMG_VOID) GetTempBuffer();
+
+       
+       PDumpInit();
+}
+
+IMG_VOID PDumpDeInitCommon(IMG_VOID)
+{
+       
+       FreeTempBuffer();
+
+       
+       PDumpDeInit();
+}
+
+IMG_BOOL PDumpIsSuspended(IMG_VOID)
+{
+       return PDumpOSIsSuspended();
+}
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+       if( _PDumpIsProcessActive() )
+       {
+               return PDumpOSIsCaptureFrameKM();
+       }
+       return IMG_FALSE;
+#else
+       return PDumpOSIsCaptureFrameKM();
+#endif
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+       if( _PDumpIsProcessActive() )
+       {
+               return PDumpOSSetFrameKM(ui32Frame);
+       }
+       return PVRSRV_OK;
+#else
+       return PDumpOSSetFrameKM(ui32Frame);
+#endif
+}
+
+
+PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+                                                               IMG_UINT32 ui32Reg,
+                                                               IMG_UINT32 ui32Data,
+                                                               IMG_UINT32 ui32Flags)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_GET_SCRIPT_STRING()
+       PDUMP_DBG(("PDumpRegWithFlagsKM"));
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :%s:0x%08X 0x%08X\r\n",
+                                                               pszPDumpRegName, ui32Reg, ui32Data);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegKM(IMG_CHAR *pszPDumpRegName,
+                                               IMG_UINT32 ui32Reg,
+                                               IMG_UINT32 ui32Data)
+{
+       return PDumpRegWithFlagsKM(pszPDumpRegName, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+                                                                       IMG_UINT32 ui32RegAddr, 
+                                                                       IMG_UINT32 ui32RegValue, 
+                                                                       IMG_UINT32 ui32Mask,
+                                                                       IMG_UINT32 ui32Flags)
+{
+       
+       #define POLL_DELAY                      1000U
+       #define POLL_COUNT_LONG         (2000000000U / POLL_DELAY)
+       #define POLL_COUNT_SHORT        (1000000U / POLL_DELAY)
+
+       PVRSRV_ERROR eErr;
+       IMG_UINT32      ui32PollCount;
+
+       PDUMP_GET_SCRIPT_STRING();
+       PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
+       if ( _PDumpIsPersistent() )
+       {
+               
+               return PVRSRV_OK;
+       }
+
+#if 0
+       if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+               (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK) != 0) ||
+           ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+               (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK) != 0) ||
+           ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+               (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK) != 0))
+       {
+               ui32PollCount = POLL_COUNT_LONG;
+       }
+       else
+#endif
+       {
+               ui32PollCount = POLL_COUNT_LONG;
+       }
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :%s:0x%08X 0x%08X 0x%08X %d %u %d\r\n",
+                                                       pszPDumpRegName, ui32RegAddr, ui32RegValue,
+                                                       ui32Mask, 0, ui32PollCount, POLL_DELAY);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask)
+{
+       return PDumpRegPolWithFlagsKM(pszPDumpRegName, ui32RegAddr, ui32RegValue, ui32Mask, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER        *psDevID,
+                           IMG_UINT32         ui32DevVAddr,
+                           IMG_CPU_VIRTADDR   pvLinAddr,
+                           IMG_HANDLE         hOSMemHandle,
+                           IMG_UINT32         ui32NumBytes,
+                           IMG_UINT32         ui32PageSize,
+                           IMG_BOOL                      bShared,
+                           IMG_HANDLE         hUniqueTag)
+{
+       PVRSRV_ERROR eErr;
+       IMG_PUINT8              pui8LinAddr;
+    IMG_UINT32      ui32Offset;
+       IMG_UINT32              ui32NumPages;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_UINT32              ui32Page;
+       IMG_UINT32              ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+
+       PDUMP_GET_SCRIPT_STRING();
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+       ui32Flags |= ( _PDumpIsPersistent() || bShared ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#else
+       PVR_UNREFERENCED_PARAMETER(bShared);
+       ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+       
+#if !defined(LINUX)
+       PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & HOST_PAGEMASK) == 0);
+#endif
+
+       PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & HOST_PAGEMASK) == 0);
+       PVR_ASSERT(((IMG_UINT32) ui32NumBytes & HOST_PAGEMASK) == 0);
+
+       
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :%s:VA_%08X 0x%08X %u\r\n",
+                       psDevID->pszPDumpDevName, ui32DevVAddr, ui32NumBytes, ui32PageSize);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       
+
+       pui8LinAddr = (IMG_PUINT8) pvLinAddr;
+       ui32Offset = 0;
+       ui32NumPages = ui32NumBytes / ui32PageSize;
+       while (ui32NumPages)
+       { 
+               ui32NumPages--;
+
+               
+
+
+
+
+
+
+               
+               
+               
+               PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
+                               hOSMemHandle,
+                               ui32Offset,
+                               pui8LinAddr,
+                               ui32PageSize,
+                               &sDevPAddr);
+               ui32Page = (IMG_UINT32)(sDevPAddr.uiAddr / ui32PageSize);
+               
+               pui8LinAddr     += ui32PageSize;
+               ui32Offset += ui32PageSize;
+
+               eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:PA_%08X%08X %u %u 0x%08X\r\n",
+                                                                                               psDevID->pszPDumpDevName,
+                                                                                               (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                                                                                               ui32Page * ui32PageSize,
+                                                                                               ui32PageSize,
+                                                                                               ui32PageSize,
+                                                                                               ui32Page * ui32PageSize);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+               PDumpOSWriteString2(hScript, ui32Flags);
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER    *psDevId,
+                                                                  IMG_HANDLE hOSMemHandle,
+                                                                  IMG_UINT32 ui32Offset,
+                               IMG_CPU_VIRTADDR   pvLinAddr,
+                                                               IMG_UINT32        ui32PTSize,
+                                                                  IMG_UINT32 ui32Flags,
+                               IMG_HANDLE         hUniqueTag)
+{
+       PVRSRV_ERROR eErr;
+       IMG_DEV_PHYADDR sDevPAddr;
+
+       PDUMP_GET_SCRIPT_STRING();
+
+       PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize - 1)) == 0);
+       ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+       ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+       
+
+       eErr = PDumpOSBufprintf(hScript,
+                                                       ui32MaxLen,
+                                                       "-- MALLOC :%s:PAGE_TABLE 0x%08X %u\r\n",
+                                                       psDevId->pszPDumpDevName,
+                                                       ui32PTSize,
+                                                       ui32PTSize);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       
+
+       
+       
+       
+       
+
+       PDumpOSCPUVAddrToDevPAddr(psDevId->eDeviceType,
+                       hOSMemHandle, 
+                       ui32Offset,
+                       (IMG_PUINT8) pvLinAddr,
+                       ui32PTSize,
+                       &sDevPAddr);
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:PA_%08X%08X 0x%X %u 0x%08X\r\n",
+                                                                                       psDevId->pszPDumpDevName,
+                                                                                       (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                                                                                       sDevPAddr.uiAddr,
+                                                                                       ui32PTSize,
+                                                                                       ui32PTSize,
+                                                                                       sDevPAddr.uiAddr);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePages    (BM_HEAP                        *psBMHeap,
+                         IMG_DEV_VIRTADDR  sDevVAddr,
+                         IMG_UINT32        ui32NumBytes,
+                         IMG_UINT32        ui32PageSize,
+                         IMG_HANDLE        hUniqueTag,
+                                                IMG_BOOL                  bInterleaved)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32 ui32NumPages, ui32PageCounter;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PDUMP_GET_SCRIPT_STRING();
+
+       PVR_ASSERT(((IMG_UINT32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
+       PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+       psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+       ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+       
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:VA_%08X\r\n", 
+                                                       psDeviceNode->sDevId.pszPDumpDevName, sDevVAddr.uiAddr);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+       {
+               PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+               if( psDeviceNode->pfnMMUIsHeapShared(psBMHeap->pMMUHeap) )
+               {
+                       ui32Flags |= PDUMP_FLAGS_PERSISTENT;
+               }
+       }
+#endif
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       
+
+       ui32NumPages = ui32NumBytes / ui32PageSize;
+       for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages; ui32PageCounter++)
+       {
+               if (!bInterleaved || (ui32PageCounter % 2) == 0)
+               {
+                       sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->pMMUHeap, sDevVAddr);
+                       {
+                               eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_%08X%08X\r\n",
+                                                                               psDeviceNode->sDevId.pszPDumpDevName, (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag, sDevPAddr.uiAddr);
+                               if(eErr != PVRSRV_OK)
+                               {
+                                       return eErr;
+                               }
+                               PDumpOSWriteString2(hScript, ui32Flags);
+                       }
+               }
+               else
+               {
+                       
+               }
+
+               sDevVAddr.uiAddr += ui32PageSize;
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePageTable        (PVRSRV_DEVICE_IDENTIFIER *psDevID,
+                                                                IMG_HANDLE hOSMemHandle,
+                                                                IMG_CPU_VIRTADDR   pvLinAddr,
+                                                                IMG_UINT32         ui32PTSize,
+                                                                IMG_UINT32                     ui32Flags,
+                                                                IMG_HANDLE         hUniqueTag)
+{
+       PVRSRV_ERROR eErr;
+       IMG_DEV_PHYADDR sDevPAddr;
+
+       PDUMP_GET_SCRIPT_STRING();
+
+       PVR_UNREFERENCED_PARAMETER(ui32PTSize);
+       ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+       ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+       
+       PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize-1UL)) == 0); 
+
+       
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:PAGE_TABLE\r\n", psDevID->pszPDumpDevName);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       
+
+       
+       
+       
+       
+
+       PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
+                                                         hOSMemHandle, 
+                       0,
+                       (IMG_PUINT8) pvLinAddr,
+                       ui32PTSize,
+                       &sDevPAddr);
+
+       {
+               eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_%08X%08X\r\n",
+                                                               psDevID->pszPDumpDevName,
+                                                               (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                                                               sDevPAddr.uiAddr);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+               PDumpOSWriteString2(hScript, ui32Flags);
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                       IMG_UINT32 ui32Reg,
+                                                        IMG_UINT32 ui32Data,
+                                                        IMG_UINT32     ui32Flags,
+                                                        IMG_HANDLE hUniqueTag)
+{
+       PVRSRV_ERROR eErr;
+       IMG_CHAR *pszRegString;
+       PDUMP_GET_SCRIPT_STRING()
+       
+       if(psMMUAttrib->pszPDRegRegion != IMG_NULL)
+       {       
+               pszRegString = psMMUAttrib->pszPDRegRegion;
+       }
+       else
+       {
+               pszRegString = psMMUAttrib->sDevId.pszPDumpRegName;
+       }
+
+       
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+                        "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+                        psMMUAttrib->sDevId.pszPDumpDevName,
+                        psMMUAttrib->sDevId.pszPDumpDevName,
+                        (IMG_UINT32)hUniqueTag,
+                        (ui32Data & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PDEAlignShift);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :%s:$1 :%s:$1 0x4\r\n", 
+                       psMMUAttrib->sDevId.pszPDumpDevName,
+                       psMMUAttrib->sDevId.pszPDumpDevName);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+                        "WRW :%s:0x%08X: %s:$1\r\n",
+                        pszRegString,
+                        ui32Reg,
+                        psMMUAttrib->sDevId.pszPDumpDevName);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+#else
+       eErr = PDumpOSBufprintf(hScript,
+                               ui32MaxLen,
+                               "WRW :%s:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+                               pszRegString,
+                               ui32Reg,
+                               psMMUAttrib->sDevId.pszPDumpDevName,
+                               (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                               (ui32Data & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PDEAlignShift,
+                               ui32Data & ~psMMUAttrib->ui32PDEMask);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDReg        (PDUMP_MMU_ATTRIB *psMMUAttrib, 
+                                        IMG_UINT32 ui32Reg,
+                                        IMG_UINT32 ui32Data,
+                                        IMG_HANDLE hUniqueTag)
+{
+       return PDumpPDRegWithFlags(psMMUAttrib, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
+}
+
+PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO              *psMemInfo,
+                                                  IMG_UINT32                   ui32Offset,
+                                                  IMG_UINT32                   ui32Value,
+                                                  IMG_UINT32                   ui32Mask,
+                                                  PDUMP_POLL_OPERATOR  eOperator,
+                                                  IMG_UINT32                   ui32Flags,
+                                                  IMG_HANDLE                   hUniqueTag)
+{
+       #define MEMPOLL_DELAY           (1000)
+       #define MEMPOLL_COUNT           (2000000000 / MEMPOLL_DELAY)
+
+       PVRSRV_ERROR eErr;
+       IMG_UINT32                      ui32PageOffset;
+       IMG_UINT8                       *pui8LinAddr;
+       IMG_DEV_PHYADDR         sDevPAddr;
+       IMG_DEV_VIRTADDR        sDevVPageAddr;
+       PDUMP_MMU_ATTRIB        *psMMUAttrib;
+
+       PDUMP_GET_SCRIPT_STRING();
+       if ( _PDumpIsPersistent() )
+       {
+               
+               return PVRSRV_OK;
+       }
+
+       
+       PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <= psMemInfo->ui32AllocSize);
+
+       psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+       
+
+       eErr = PDumpOSBufprintf(hScript,
+                        ui32MaxLen,
+                        "-- POL :%s:VA_%08X 0x%08X 0x%08X %d %d %d\r\n",
+                        psMMUAttrib->sDevId.pszPDumpDevName,
+                        psMemInfo->sDevVAddr.uiAddr + ui32Offset,
+                        ui32Value,
+                        ui32Mask,
+                        eOperator,
+                        MEMPOLL_COUNT,
+                        MEMPOLL_DELAY);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+
+       pui8LinAddr = psMemInfo->pvLinAddrKM;
+
+       
+       pui8LinAddr += ui32Offset;
+
+       
+
+
+       PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+                       ui32Offset,
+                       pui8LinAddr,
+                       psMMUAttrib->ui32DataPageMask,
+                       &ui32PageOffset);
+
+       
+       sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+       PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
+
+       
+       BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+       
+       sDevPAddr.uiAddr += ui32PageOffset;
+
+       eErr = PDumpOSBufprintf(hScript,
+                        ui32MaxLen,
+                        "POL :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %d %d %d\r\n",
+                        psMMUAttrib->sDevId.pszPDumpDevName,
+                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                        sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+                        sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+                        ui32Value,
+                        ui32Mask,
+                        eOperator,
+                        MEMPOLL_COUNT,
+                        MEMPOLL_DELAY);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+                                               PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                               IMG_UINT32 ui32Offset,
+                                               IMG_UINT32 ui32Bytes,
+                                               IMG_UINT32 ui32Flags,
+                                               IMG_HANDLE hUniqueTag)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32 ui32NumPages;
+       IMG_UINT32 ui32PageByteOffset;
+       IMG_UINT32 ui32BlockBytes;
+       IMG_UINT8* pui8LinAddr;
+       IMG_UINT8* pui8DataLinAddr = IMG_NULL;
+       IMG_DEV_VIRTADDR sDevVPageAddr;
+       IMG_DEV_VIRTADDR sDevVAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_UINT32 ui32ParamOutPos;
+       PDUMP_MMU_ATTRIB *psMMUAttrib;
+       IMG_UINT32 ui32DataPageSize;
+
+       PDUMP_GET_SCRIPT_AND_FILE_STRING();
+       
+       psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+       
+       
+
+       PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize);
+
+       if (!PDumpOSJTInitialised())
+       {
+               return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+       }
+
+        
+       if (ui32Bytes == 0 || PDumpOSIsSuspended())
+       {
+               return PVRSRV_OK;
+       }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+       {
+               BM_HEAP *pHeap = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap;
+               PVRSRV_DEVICE_NODE *psDeviceNode = pHeap->pBMContext->psDeviceNode;
+
+               if( psDeviceNode->pfnMMUIsHeapShared(pHeap->pMMUHeap) )
+               {
+                       ui32Flags |= PDUMP_FLAGS_PERSISTENT;
+               }
+       }
+#endif
+
+       
+       if(pvAltLinAddr)
+       {
+               pui8DataLinAddr = pvAltLinAddr;
+       }
+       else if(psMemInfo->pvLinAddrKM)
+       {
+               pui8DataLinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM + ui32Offset;
+       }
+       pui8LinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM;
+       sDevVAddr = psMemInfo->sDevVAddr;
+
+       
+       sDevVAddr.uiAddr += ui32Offset;
+       pui8LinAddr += ui32Offset;
+
+       PVR_ASSERT(pui8DataLinAddr);
+
+       PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+       ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+       
+
+       if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+                                               pui8DataLinAddr,
+                                               ui32Bytes,
+                                               ui32Flags))
+       {
+               return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+       }
+
+       if (PDumpOSGetParamFileNum() == 0)
+       {
+               eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+       }
+       else
+       {
+               eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+       }
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       
+
+       eErr = PDumpOSBufprintf(hScript,
+                        ui32MaxLenScript,
+                        "-- LDB :%s:VA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+                        psMMUAttrib->sDevId.pszPDumpDevName,
+                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                        psMemInfo->sDevVAddr.uiAddr,
+                        ui32Offset,
+                        ui32Bytes,
+                        ui32ParamOutPos,
+                        pszFileName);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       
+
+
+       PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+                       ui32Offset,
+                       pui8LinAddr,
+                       psMMUAttrib->ui32DataPageMask,
+                       &ui32PageByteOffset);
+       ui32DataPageSize = psMMUAttrib->ui32DataPageMask + 1;
+       ui32NumPages = (ui32PageByteOffset + ui32Bytes + psMMUAttrib->ui32DataPageMask) / ui32DataPageSize;
+
+       while(ui32NumPages)
+       {
+               ui32NumPages--;
+       
+               
+               sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+
+               if (ui32DataPageSize <= PDUMP_TEMP_BUFFER_SIZE)
+               {
+                       
+                       PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
+               }
+
+               
+               BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+               
+               sDevPAddr.uiAddr += ui32PageByteOffset;
+
+               
+               if (ui32PageByteOffset + ui32Bytes > ui32DataPageSize)
+               {
+                       
+                       ui32BlockBytes = ui32DataPageSize - ui32PageByteOffset;
+               }
+               else
+               {
+                       
+                       ui32BlockBytes = ui32Bytes;
+               }
+
+               eErr = PDumpOSBufprintf(hScript,
+                                        ui32MaxLenScript,
+                                        "LDB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+                                        psMMUAttrib->sDevId.pszPDumpDevName,
+                                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                                        sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+                                        sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+                                        ui32BlockBytes,
+                                        ui32ParamOutPos,
+                                        pszFileName);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+               PDumpOSWriteString2(hScript, ui32Flags);
+
+               
+
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+               
+               ui32PageByteOffset = (ui32PageByteOffset + ui32BlockBytes) % ui32DataPageSize;
+#else
+               
+               ui32PageByteOffset = 0;
+#endif
+               
+               ui32Bytes -= ui32BlockBytes;     
+               
+               sDevVAddr.uiAddr += ui32BlockBytes;
+               
+               pui8LinAddr += ui32BlockBytes;
+               
+               ui32ParamOutPos += ui32BlockBytes;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                                IMG_HANDLE hOSMemHandle,
+                                                                IMG_CPU_VIRTADDR pvLinAddr,
+                                                                IMG_UINT32 ui32Bytes,
+                                                                IMG_UINT32 ui32Flags,
+                                                                IMG_BOOL bInitialisePages,
+                                                                IMG_HANDLE hUniqueTag1,
+                                                                IMG_HANDLE hUniqueTag2)
+{
+       PDUMP_MMU_ATTRIB sMMUAttrib;
+       
+       
+       sMMUAttrib = *psMMUAttrib;
+       sMMUAttrib.ui32PTSize = HOST_PAGESIZE();
+       return PDumpMemPTEntriesKM(     &sMMUAttrib,
+                                                               hOSMemHandle,
+                                                               pvLinAddr,
+                                                               ui32Bytes,
+                                                               ui32Flags,
+                                                               bInitialisePages,
+                                                               hUniqueTag1,
+                                                               hUniqueTag2);
+}
+
+PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                                IMG_HANDLE hOSMemHandle,
+                                                                IMG_CPU_VIRTADDR pvLinAddr,
+                                                                IMG_UINT32 ui32Bytes,
+                                                                IMG_UINT32 ui32Flags,
+                                                                IMG_BOOL bInitialisePages,
+                                                                IMG_HANDLE hUniqueTag1,
+                                                                IMG_HANDLE hUniqueTag2)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32 ui32NumPages;
+       IMG_UINT32 ui32PageOffset;
+       IMG_UINT32 ui32BlockBytes;
+       IMG_UINT8* pui8LinAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_CPU_PHYADDR sCpuPAddr;
+       IMG_UINT32 ui32Offset;
+       IMG_UINT32 ui32ParamOutPos;
+       IMG_UINT32 ui32PageMask; 
+
+       PDUMP_GET_SCRIPT_AND_FILE_STRING();
+       ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+       if (!PDumpOSJTInitialised())
+       {
+               return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+       }
+
+       if (!pvLinAddr)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (PDumpOSIsSuspended())
+       {
+               return PVRSRV_OK;
+       }
+
+       PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+       ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+       if (bInitialisePages)
+       {
+               
+
+
+               if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+                                                       pvLinAddr,
+                                                       ui32Bytes,
+                                                       ui32Flags | PDUMP_FLAGS_CONTINUOUS))
+               {
+                       return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+               }
+
+               if (PDumpOSGetParamFileNum() == 0)
+               {
+                       eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+               }
+               else
+               {
+                       eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+               }
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+       }
+
+       
+
+
+
+
+       ui32PageMask = psMMUAttrib->ui32PTSize - 1;
+
+       
+
+       
+       ui32PageOffset  = (IMG_UINT32)((IMG_UINTPTR_T)pvLinAddr & (psMMUAttrib->ui32PTSize - 1));
+       ui32NumPages    = (ui32PageOffset + ui32Bytes + psMMUAttrib->ui32PTSize - 1) / psMMUAttrib->ui32PTSize;
+       pui8LinAddr             = (IMG_UINT8*) pvLinAddr;
+
+       while (ui32NumPages)
+       {
+               ui32NumPages--;
+               
+
+
+
+
+
+               sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
+               sDevPAddr = SysCpuPAddrToDevPAddr(psMMUAttrib->sDevId.eDeviceType, sCpuPAddr);
+
+               
+               if (ui32PageOffset + ui32Bytes > psMMUAttrib->ui32PTSize)
+               {
+                       
+                       ui32BlockBytes = psMMUAttrib->ui32PTSize - ui32PageOffset;
+               }
+               else
+               {
+                       
+                       ui32BlockBytes = ui32Bytes;
+               }
+
+               
+
+               
+               if (bInitialisePages)
+               {
+                       eErr = PDumpOSBufprintf(hScript,
+                                        ui32MaxLenScript,
+                                        "LDB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+                                        psMMUAttrib->sDevId.pszPDumpDevName,
+                                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+                                        sDevPAddr.uiAddr & ~ui32PageMask,
+                                        sDevPAddr.uiAddr & ui32PageMask,
+                                        ui32BlockBytes,
+                                        ui32ParamOutPos,
+                                        pszFileName);
+                       if(eErr != PVRSRV_OK)
+                       {
+                               return eErr;
+                       }
+                       PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+               }
+               else
+               {
+                       for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(IMG_UINT32))
+                       {
+                               IMG_UINT32 ui32PTE = *((IMG_UINT32 *) (pui8LinAddr + ui32Offset));  
+
+                               if ((ui32PTE & psMMUAttrib->ui32PDEMask) != 0)
+                               {
+                                       
+#if defined(SGX_FEATURE_36BIT_MMU)
+                                       eErr = PDumpOSBufprintf(hScript,
+                                                       ui32MaxLenScript,
+                                                        "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+                                                        psMMUAttrib->sDevId.pszPDumpDevName,
+                                                        psMMUAttrib->sDevId.pszPDumpDevName,
+                                                        (IMG_UINT32)hUniqueTag2,
+                                                        (ui32PTE & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PTEAlignShift);
+                                       if(eErr != PVRSRV_OK)
+                                       {
+                                               return eErr;
+                                       }
+                                       PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+                                       eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :%s:$1 :%s:$1 0x4\r\n",
+                                                               psMMUAttrib->sDevId.pszPDumpDevName,
+                                                               psMMUAttrib->sDevId.pszPDumpDevName);
+                                       if(eErr != PVRSRV_OK)
+                                       {
+                                               return eErr;
+                                       }
+                                       PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+                                       eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "OR :%s:$1 :%s:$1 0x%08X\r\n",
+                                                               psMMUAttrib->sDevId.pszPDumpDevName,
+                                                               psMMUAttrib->sDevId.pszPDumpDevName,
+                                                               ui32PTE & ~psMMUAttrib->ui32PDEMask);
+                                       if(eErr != PVRSRV_OK)
+                                       {
+                                               return eErr;
+                                       }
+                                       PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+                                       eErr = PDumpOSBufprintf(hScript,
+                                                       ui32MaxLenScript,
+                                                        "WRW :%s:PA_%08X%08X:0x%08X :%s:$1\r\n",
+                                                        psMMUAttrib->sDevId.pszPDumpDevName,
+                                                        (IMG_UINT32)hUniqueTag1,
+                                                        (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+                                                        (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+                                                        psMMUAttrib->sDevId.pszPDumpDevName);
+                                       if(eErr != PVRSRV_OK)
+                                       {
+                                               return eErr;
+                                       }
+                                       PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+#else
+                                       eErr = PDumpOSBufprintf(hScript,
+                                                       ui32MaxLenScript,
+                                                        "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+                                                        psMMUAttrib->sDevId.pszPDumpDevName,
+                                                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+                                                        (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+                                                        (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+                                                        psMMUAttrib->sDevId.pszPDumpDevName,
+                                                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2,
+                                                        (ui32PTE & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PTEAlignShift,
+                                                        ui32PTE & ~psMMUAttrib->ui32PDEMask);
+                                       if(eErr != PVRSRV_OK)
+                                       {
+                                               return eErr;
+                                       }
+                                       PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+#endif
+                               }
+                               else
+                               {
+                                       PVR_ASSERT((ui32PTE & psMMUAttrib->ui32PTEValid) == 0UL);
+                                       eErr = PDumpOSBufprintf(hScript,
+                                                       ui32MaxLenScript,
+                                                        "WRW :%s:PA_%08X%08X:0x%08X 0x%08X%08X\r\n",
+                                                        psMMUAttrib->sDevId.pszPDumpDevName,
+                                                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+                                                        (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+                                                        (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+                                                        (ui32PTE << psMMUAttrib->ui32PTEAlignShift),
+                                                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2);
+                                       if(eErr != PVRSRV_OK)
+                                       {
+                                               return eErr;
+                                       }
+                                       PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+                               }
+                       }
+               }
+
+               
+
+               
+               ui32PageOffset = 0;
+               
+               ui32Bytes -= ui32BlockBytes;
+               
+               pui8LinAddr += ui32BlockBytes;
+               
+               ui32ParamOutPos += ui32BlockBytes;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                          IMG_UINT32 ui32Offset,
+                                                          IMG_DEV_PHYADDR sPDDevPAddr,
+                                                          IMG_HANDLE hUniqueTag1,
+                                                          IMG_HANDLE hUniqueTag2)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32 ui32PageByteOffset;
+       IMG_DEV_VIRTADDR sDevVAddr;
+       IMG_DEV_VIRTADDR sDevVPageAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+       IMG_UINT32 ui32ParamOutPos;
+       PDUMP_MMU_ATTRIB *psMMUAttrib;
+       IMG_UINT32 ui32PageMask; 
+
+       PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+       if (!PDumpOSJTInitialised())
+       {
+               return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+       }
+
+       psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+       ui32PageMask = psMMUAttrib->ui32PTSize - 1;
+
+       ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+       
+       if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+                                               (IMG_UINT8 *)&sPDDevPAddr,
+                                               sizeof(IMG_DEV_PHYADDR),
+                                               ui32Flags))
+       {
+               return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+       }
+
+       if (PDumpOSGetParamFileNum() == 0)
+       {
+               eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+       }
+       else
+       {
+               eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+       }
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       
+       eErr = PDumpOSBufprintf(hScript,
+                       ui32MaxLenScript,
+                       "-- LDB :%s:PA_0x%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+                       psMMUAttrib->sDevId.pszPDumpDevName,
+                       (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+                       sPDDevPAddr.uiAddr & ~ui32PageMask,
+                       sPDDevPAddr.uiAddr & ui32PageMask,
+                       sizeof(IMG_DEV_PHYADDR),
+                       ui32ParamOutPos,
+                       pszFileName);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       
+       sDevVAddr = psMemInfo->sDevVAddr;
+       ui32PageByteOffset = sDevVAddr.uiAddr & ui32PageMask;
+
+       sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+       PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+       BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+       sDevPAddr.uiAddr += ui32PageByteOffset + ui32Offset;
+
+       if ((sPDDevPAddr.uiAddr & psMMUAttrib->ui32PDEMask) != 0UL)
+       {
+#if defined(SGX_FEATURE_36BIT_MMU)
+               eErr = PDumpOSBufprintf(hScript,
+                               ui32MaxLenScript,
+                                "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+                                psMMUAttrib->sDevId.pszPDumpDevName,
+                                psMMUAttrib->sDevId.pszPDumpDevName,
+                                (IMG_UINT32)hUniqueTag2,
+                                sPDDevPAddr.uiAddr);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+               PDumpOSWriteString2(hScript, ui32Flags);
+
+               eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "AND  :%s:$2 :%s:$1 0xFFFFFFFF\r\n",
+                                       psMMUAttrib->sDevId.pszPDumpDevName,
+                                       psMMUAttrib->sDevId.pszPDumpDevName);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+               PDumpOSWriteString2(hScript, ui32Flags);
+
+               eErr = PDumpOSBufprintf(hScript,
+                               ui32MaxLenScript,
+                                "WRW :%s:PA_%08X%08X:0x%08X :%s:$2\r\n",
+                                psMMUAttrib->sDevId.pszPDumpDevName,
+                                (IMG_UINT32)hUniqueTag1,
+                                (sDevPAddr.uiAddr) & ~(psMMUAttrib->ui32DataPageMask),
+                                (sDevPAddr.uiAddr) & (psMMUAttrib->ui32DataPageMask),
+                                psMMUAttrib->sDevId.pszPDumpDevName);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+               PDumpOSWriteString2(hScript, ui32Flags);
+
+               eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :%s:$2 :%s:$1 0x20\r\n",
+                               psMMUAttrib->sDevId.pszPDumpDevName,
+                               psMMUAttrib->sDevId.pszPDumpDevName);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+               PDumpOSWriteString2(hScript, ui32Flags);
+
+               eErr = PDumpOSBufprintf(hScript,
+                               ui32MaxLenScript,
+                                "WRW :%s:PA_%08X%08X:0x%08X :%s:$2\r\n",
+                                psMMUAttrib->sDevId.pszPDumpDevName,
+                                (IMG_UINT32)hUniqueTag1,
+                                (sDevPAddr.uiAddr + 4) & ~(psMMUAttrib->ui32DataPageMask),
+                                (sDevPAddr.uiAddr + 4) & (psMMUAttrib->ui32DataPageMask),
+                                psMMUAttrib->sDevId.pszPDumpDevName);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+               PDumpOSWriteString2(hScript, ui32Flags);
+#else
+               eErr = PDumpOSBufprintf(hScript,
+                                ui32MaxLenScript,
+                                "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+                                psMMUAttrib->sDevId.pszPDumpDevName,
+                                (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+                                sDevPAddr.uiAddr & ~ui32PageMask,
+                                sDevPAddr.uiAddr & ui32PageMask,
+                                psMMUAttrib->sDevId.pszPDumpDevName,
+                                (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2,
+                                sPDDevPAddr.uiAddr & psMMUAttrib->ui32PDEMask,
+                                sPDDevPAddr.uiAddr & ~psMMUAttrib->ui32PDEMask);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+#endif
+       }
+       else
+       {
+               PVR_ASSERT(!(sDevPAddr.uiAddr & psMMUAttrib->ui32PTEValid));
+               eErr = PDumpOSBufprintf(hScript,
+                                ui32MaxLenScript,
+                                "WRW :%s:PA_%08X%08X:0x%08X 0x%08X\r\n",
+                                psMMUAttrib->sDevId.pszPDumpDevName,
+                                (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+                                sDevPAddr.uiAddr & ~ui32PageMask,
+                                sDevPAddr.uiAddr & ui32PageMask,
+                                sPDDevPAddr.uiAddr);
+               if(eErr != PVRSRV_OK)
+               {
+                       return eErr;
+               }
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+{
+       PVRSRV_ERROR eErr;
+       IMG_CHAR pszCommentPrefix[] = "-- "; 
+#if defined(PDUMP_DEBUG_OUTFILES)
+       IMG_CHAR pszTemp[256];
+#endif
+       IMG_UINT32 ui32LenCommentPrefix;
+       PDUMP_GET_SCRIPT_STRING();
+       PDUMP_DBG(("PDumpCommentKM"));
+#if defined(PDUMP_DEBUG_OUTFILES)
+       
+       ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+       
+       PDumpOSVerifyLineEnding(pszComment, ui32MaxLen);
+
+       
+       ui32LenCommentPrefix = PDumpOSBuflen(pszCommentPrefix, sizeof(pszCommentPrefix));
+
+       
+       if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_SCRIPT2),
+                         (IMG_UINT8*)pszCommentPrefix,
+                         ui32LenCommentPrefix,
+                         ui32Flags))
+       {
+               if(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+               {
+                       return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+               }
+               else
+               {
+                       return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+               }
+       }
+#if defined(PDUMP_DEBUG_OUTFILES)
+       
+       eErr = PDumpOSSprintf(pszTemp, 256, "%d-%d %s",
+               _PDumpGetPID(),
+               g_ui32EveryLineCounter,
+               pszComment);
+
+       
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
+               pszTemp);
+#else
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
+               pszComment);
+#endif
+       if( (eErr != PVRSRV_OK) &&
+               (eErr != PVRSRV_ERROR_PDUMP_BUF_OVERFLOW))
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_va_list ap;
+       PDUMP_GET_MSG_STRING();
+
+       
+       PDUMP_va_start(ap, pszFormat);
+       eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+       PDUMP_va_end(ap);
+
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       return PDumpCommentKM(pszMsg, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_va_list ap;
+       PDUMP_GET_MSG_STRING();
+
+       
+       PDUMP_va_start(ap, pszFormat);
+       eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+       PDUMP_va_end(ap);
+
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       return PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32      ui32MsgLen;
+       PDUMP_GET_MSG_STRING();
+
+       
+       eErr = PDumpOSSprintf(pszMsg, ui32MaxLen, "%s", pszString);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       
+       PDumpOSVerifyLineEnding(pszMsg, ui32MaxLen);
+       ui32MsgLen = PDumpOSBuflen(pszMsg, ui32MaxLen);
+
+       if      (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_DRIVERINFO),
+                                                 (IMG_UINT8*)pszMsg,
+                                                 ui32MsgLen,
+                                                 ui32Flags))
+       {
+               if      (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+               {
+                       return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+               }
+               else
+               {
+                       return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+               }
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpBitmapKM(    PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_CHAR *pszFileName,
+                                                       IMG_UINT32 ui32FileOffset,
+                                                       IMG_UINT32 ui32Width,
+                                                       IMG_UINT32 ui32Height,
+                                                       IMG_UINT32 ui32StrideInBytes,
+                                                       IMG_DEV_VIRTADDR sDevBaseAddr,
+                                                       IMG_HANDLE hDevMemContext,
+                                                       IMG_UINT32 ui32Size,
+                                                       PDUMP_PIXEL_FORMAT ePixelFormat,
+                                                       PDUMP_MEM_FORMAT eMemFormat,
+                                                       IMG_UINT32 ui32PDumpFlags)
+{
+       PVRSRV_DEVICE_IDENTIFIER *psDevId = &psDeviceNode->sDevId;
+       
+       PVRSRV_ERROR eErr;
+       PDUMP_GET_SCRIPT_STRING();
+
+       if ( _PDumpIsPersistent() )
+       {
+               return PVRSRV_OK;
+       }
+
+       PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump bitmap of render\r\n");
+
+       
+       
+       
+       PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+       
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       
+       eErr = PDumpOSBufprintf(hScript,
+                               ui32MaxLen,
+                               "SII %s %s.bin :%s:v%x:0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+                               pszFileName,
+                               pszFileName,
+                               psDevId->pszPDumpDevName,
+                               PDUMP_DATAMASTER_PIXEL,
+                               sDevBaseAddr.uiAddr,
+                               ui32Size,
+                               ui32FileOffset,
+                               ePixelFormat,
+                               ui32Width,
+                               ui32Height,
+                               ui32StrideInBytes,
+                               eMemFormat);
+#else
+       eErr = PDumpOSBufprintf(hScript,
+                               ui32MaxLen,
+                               "SII %s %s.bin :%s:v:0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+                               pszFileName,
+                               pszFileName,
+                               psDevId->pszPDumpDevName,
+                               sDevBaseAddr.uiAddr,
+                               ui32Size,
+                               ui32FileOffset,
+                               ePixelFormat,
+                               ui32Width,
+                               ui32Height,
+                               ui32StrideInBytes,
+                               eMemFormat);
+#endif
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       PDumpOSWriteString2( hScript, ui32PDumpFlags);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpReadRegKM            (       IMG_CHAR *pszPDumpRegName,
+                                                                       IMG_CHAR *pszFileName,
+                                                                       IMG_UINT32 ui32FileOffset,
+                                                                       IMG_UINT32 ui32Address,
+                                                                       IMG_UINT32 ui32Size,
+                                                                       IMG_UINT32 ui32PDumpFlags)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_GET_SCRIPT_STRING();
+
+       PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+       eErr = PDumpOSBufprintf(hScript,
+                       ui32MaxLen,
+                       "SAB :%s:0x%08X 0x%08X %s\r\n",
+                       pszPDumpRegName,
+                       ui32Address,
+                       ui32FileOffset,
+                       pszFileName);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       PDumpOSWriteString2( hScript, ui32PDumpFlags);
+
+       return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
+{
+       IMG_BOOL        bFrameDumped;
+
+       
+
+       (IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame + 1);
+       bFrameDumped = PDumpIsCaptureFrameKM();
+       (IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame);
+
+       return bFrameDumped;
+}
+
+static PVRSRV_ERROR PDumpSignatureRegister     (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                        IMG_CHAR       *pszFileName,
+                                                                        IMG_UINT32             ui32Address,
+                                                                        IMG_UINT32             ui32Size,
+                                                                        IMG_UINT32             *pui32FileOffset,
+                                                                        IMG_UINT32             ui32Flags)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_GET_SCRIPT_STRING();
+
+       eErr = PDumpOSBufprintf(hScript,
+                       ui32MaxLen,
+                       "SAB :%s:0x%08X 0x%08X %s\r\n",
+                       psDevId->pszPDumpRegName,
+                       ui32Address,
+                       *pui32FileOffset,
+                       pszFileName);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       PDumpOSWriteString2(hScript, ui32Flags);
+       *pui32FileOffset += ui32Size;
+       return PVRSRV_OK;
+}
+
+static IMG_VOID PDumpRegisterRange(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                       IMG_CHAR *pszFileName,
+                                                                       IMG_UINT32 *pui32Registers,
+                                                                       IMG_UINT32  ui32NumRegisters,
+                                                                       IMG_UINT32 *pui32FileOffset,
+                                                                       IMG_UINT32      ui32Size,
+                                                                       IMG_UINT32      ui32Flags)
+{
+       IMG_UINT32 i;
+       for (i = 0; i < ui32NumRegisters; i++)
+       {
+               PDumpSignatureRegister(psDevId, pszFileName, pui32Registers[i], ui32Size, pui32FileOffset, ui32Flags);
+       }
+}
+
+PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                               IMG_UINT32 ui32DumpFrameNum,
+                                                                               IMG_BOOL bLastFrame,
+                                                                               IMG_UINT32 *pui32Registers,
+                                                                               IMG_UINT32 ui32NumRegisters)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32      ui32FileOffset, ui32Flags;
+
+       PDUMP_GET_FILE_STRING();
+
+       ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+       ui32FileOffset = 0;
+
+       PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump 3D signature registers\r\n");
+       eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u_3d.sig", ui32DumpFrameNum);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       PDumpRegisterRange(psDevId,
+                                               pszFileName,
+                                               pui32Registers,
+                                               ui32NumRegisters,
+                                               &ui32FileOffset,
+                                               sizeof(IMG_UINT32),
+                                               ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpTASignatureRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                        IMG_UINT32 ui32DumpFrameNum,
+                        IMG_UINT32     ui32TAKickCount,
+                        IMG_BOOL       bLastFrame,
+                        IMG_UINT32 *pui32Registers,
+                        IMG_UINT32 ui32NumRegisters)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32      ui32FileOffset, ui32Flags;
+
+       PDUMP_GET_FILE_STRING();
+
+       ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+       ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(IMG_UINT32);
+
+       PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump TA signature registers\r\n");
+       eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u_ta.sig", ui32DumpFrameNum);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       PDumpRegisterRange(psDevId,
+                                               pszFileName, 
+                                               pui32Registers, 
+                                               ui32NumRegisters, 
+                                               &ui32FileOffset, 
+                                               sizeof(IMG_UINT32), 
+                                               ui32Flags);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCounterRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                               IMG_UINT32 ui32DumpFrameNum,
+                                                               IMG_BOOL        bLastFrame,
+                                                               IMG_UINT32 *pui32Registers,
+                                                               IMG_UINT32 ui32NumRegisters)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32      ui32FileOffset, ui32Flags;
+
+       PDUMP_GET_FILE_STRING();
+
+       ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0UL;
+       ui32FileOffset = 0UL;
+
+       PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump counter registers\r\n");
+       eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u.perf", ui32DumpFrameNum);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       PDumpRegisterRange(psDevId,
+                                               pszFileName,
+                                               pui32Registers,
+                                               ui32NumRegisters,
+                                               &ui32FileOffset,
+                                               sizeof(IMG_UINT32),
+                                               ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
+                                                       const IMG_UINT32 ui32RegOffset,
+                                                       IMG_UINT32 ui32Flags)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_GET_SCRIPT_STRING();
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X\r\n",
+                                                       pszPDumpRegName, 
+                                                       ui32RegOffset);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                        IMG_CHAR                       *pszFileName,
+                                                        IMG_UINT32                     ui32FileOffset,
+                                                        IMG_DEV_VIRTADDR       sDevBaseAddr,
+                                                        IMG_UINT32             ui32Size,
+                                                        IMG_UINT32             ui32DataMaster,
+                                                        IMG_UINT32             ui32PDumpFlags)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_GET_SCRIPT_STRING();
+       
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       PVR_UNREFERENCED_PARAMETER(ui32DataMaster);
+#endif 
+
+       eErr = PDumpOSBufprintf(hScript,
+                                                       ui32MaxLen,
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+                                                       "SAB :%s:v%x:0x%08X 0x%08X 0x%08X %s.bin\r\n",
+                                                       psDevId->pszPDumpDevName,
+                                                       ui32DataMaster,
+#else
+                                                       "SAB :%s:v:0x%08X 0x%08X 0x%08X %s.bin\r\n",
+                                                       psDevId->pszPDumpDevName,
+#endif 
+                                                       sDevBaseAddr.uiAddr,
+                                                       ui32Size,
+                                                       ui32FileOffset,
+                                                       pszFileName);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+
+       PDumpOSWriteString2(hScript, ui32PDumpFlags);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                       const IMG_UINT32 ui32RegOffset,
+                                                                       IMG_BOOL bLastFrame)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_GET_SCRIPT_STRING();
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X\r\n", 
+                                                       psDevId->pszPDumpRegName,
+                                                       ui32RegOffset);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpSignatureBuffer (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                  IMG_CHAR                     *pszFileName,
+                                                                  IMG_CHAR                     *pszBufferType,
+                                                                  IMG_UINT32           ui32FileOffset,
+                                                                  IMG_DEV_VIRTADDR     sDevBaseAddr,
+                                                                  IMG_UINT32           ui32Size,
+                                                                  IMG_UINT32           ui32PDumpFlags)
+{
+       PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump microkernel %s signature Buffer\r\n",
+                                                 pszBufferType);
+       PDumpCommentWithFlags(ui32PDumpFlags, "Buffer format (sizes in 32-bit words):\r\n");
+       PDumpCommentWithFlags(ui32PDumpFlags, "\tNumber of signatures per sample (1)\r\n");
+       PDumpCommentWithFlags(ui32PDumpFlags, "\tNumber of samples (1)\r\n");
+       PDumpCommentWithFlags(ui32PDumpFlags, "\tSignature register offsets (1 * number of signatures)\r\n");
+       PDumpCommentWithFlags(ui32PDumpFlags, "\tSignature sample values (number of samples * number of signatures)\r\n");
+       PDumpCommentWithFlags(ui32PDumpFlags, "Note: If buffer is full, last sample is final state after test completed\r\n");
+       return PDumpSaveMemKM(psDevId, pszFileName, ui32FileOffset, sDevBaseAddr, ui32Size,
+                                                 PDUMP_DATAMASTER_EDM, ui32PDumpFlags);
+}
+
+
+PVRSRV_ERROR PDumpHWPerfCBKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                         IMG_CHAR                      *pszFileName,
+                                                         IMG_UINT32            ui32FileOffset,
+                                                         IMG_DEV_VIRTADDR      sDevBaseAddr,
+                                                         IMG_UINT32            ui32Size,
+                                                         IMG_UINT32            ui32PDumpFlags)
+{
+       PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump Hardware Performance Circular Buffer\r\n");
+       return PDumpSaveMemKM(psDevId, pszFileName, ui32FileOffset, sDevBaseAddr, ui32Size,
+                                                 PDUMP_DATAMASTER_EDM, ui32PDumpFlags);
+}
+
+
+PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO          psROffMemInfo,
+                         IMG_UINT32                                    ui32ROffOffset,
+                         IMG_UINT32                                    ui32WPosVal,
+                         IMG_UINT32                                    ui32PacketSize,
+                         IMG_UINT32                                    ui32BufferSize,
+                         IMG_UINT32                                    ui32Flags,
+                         IMG_HANDLE                                    hUniqueTag)
+{
+       PVRSRV_ERROR eErr;
+       IMG_UINT32                      ui32PageOffset;
+       IMG_UINT8                       *pui8LinAddr;
+       IMG_DEV_VIRTADDR        sDevVAddr;
+       IMG_DEV_PHYADDR         sDevPAddr;
+       IMG_DEV_VIRTADDR        sDevVPageAddr;
+    
+       PDUMP_MMU_ATTRIB *psMMUAttrib;
+
+       PDUMP_GET_SCRIPT_STRING();
+
+       psMMUAttrib = ((BM_BUF*)psROffMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+       
+       PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <= psROffMemInfo->ui32AllocSize);
+
+       pui8LinAddr = psROffMemInfo->pvLinAddrKM;
+       sDevVAddr = psROffMemInfo->sDevVAddr;
+
+       
+       pui8LinAddr += ui32ROffOffset;
+       sDevVAddr.uiAddr += ui32ROffOffset;
+
+       
+
+
+       PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
+                       ui32ROffOffset,
+                       pui8LinAddr,
+                       psMMUAttrib->ui32DataPageMask,
+                       &ui32PageOffset);
+
+       
+       sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+       PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+       
+       BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+       
+       sDevPAddr.uiAddr += ui32PageOffset;
+
+       eErr = PDumpOSBufprintf(hScript,
+                        ui32MaxLen,
+                        "CBP :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+                        psMMUAttrib->sDevId.pszPDumpDevName,
+                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                        sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+                        sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+                        ui32WPosVal,
+                        ui32PacketSize,
+                        ui32BufferSize);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+{
+       PVRSRV_ERROR eErr;
+       PDUMP_GET_SCRIPT_STRING();
+       PDUMP_DBG(("PDumpIDLWithFlags"));
+
+       eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IDL %u\r\n", ui32Clocks);
+       if(eErr != PVRSRV_OK)
+       {
+               return eErr;
+       }
+       PDumpOSWriteString2(hScript, ui32Flags);
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
+{
+       return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                               IMG_PVOID pvAltLinAddrUM,
+                                               IMG_PVOID pvLinAddrUM,
+                                               PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                               IMG_UINT32 ui32Offset,
+                                               IMG_UINT32 ui32Bytes,
+                                               IMG_UINT32 ui32Flags,
+                                               IMG_HANDLE hUniqueTag)
+{
+       IMG_VOID *pvAddrUM;
+       IMG_VOID *pvAddrKM;
+       IMG_UINT32 ui32BytesDumped;
+       IMG_UINT32 ui32CurrentOffset;
+
+       if (psMemInfo->pvLinAddrKM != IMG_NULL && pvAltLinAddrUM == IMG_NULL)
+       {
+               
+               return PDumpMemKM(IMG_NULL,
+                                          psMemInfo,
+                                          ui32Offset,
+                                          ui32Bytes,
+                                          ui32Flags,
+                                          hUniqueTag);
+       }
+
+       pvAddrUM = (pvAltLinAddrUM != IMG_NULL) ? pvAltLinAddrUM : ((pvLinAddrUM != IMG_NULL) ? VPTR_PLUS(pvLinAddrUM, ui32Offset) : IMG_NULL);
+
+       pvAddrKM = GetTempBuffer();
+
+       
+       PVR_ASSERT(pvAddrUM != IMG_NULL && pvAddrKM != IMG_NULL);
+       if (pvAddrUM == IMG_NULL || pvAddrKM == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
+       {
+               PDumpCommentWithFlags(ui32Flags, "Dumping 0x%08x bytes of memory, in blocks of 0x%08x bytes", ui32Bytes, (IMG_UINT32)PDUMP_TEMP_BUFFER_SIZE);
+       }
+
+       ui32CurrentOffset = ui32Offset;
+       for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
+       {
+               PVRSRV_ERROR eError;
+               IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+
+               eError = OSCopyFromUser(psPerProc,
+                                          pvAddrKM,
+                                          pvAddrUM,
+                                          ui32BytesToDump);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+                       return eError;
+               }
+
+               eError = PDumpMemKM(pvAddrKM,
+                                          psMemInfo,
+                                          ui32CurrentOffset,
+                                          ui32BytesToDump,
+                                          ui32Flags,
+                                          hUniqueTag);
+
+               if (eError != PVRSRV_OK)
+               {
+                       
+                       if (ui32BytesDumped != 0)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+                       }
+                       PVR_ASSERT(ui32BytesDumped == 0);
+                       return eError;
+               }
+
+               VPTR_INC(pvAddrUM, ui32BytesToDump);
+               ui32CurrentOffset += ui32BytesToDump;
+               ui32BytesDumped += ui32BytesToDump;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
+{
+       IMG_UINT32 i;
+
+       
+       for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
+       {
+               if((gui16MMUContextUsage & (1U << i)) == 0)
+               {
+                       
+                       gui16MMUContextUsage |= 1U << i;
+                       *pui32MMUContextID = i;
+                       return PVRSRV_OK;
+               }
+       }
+
+       PVR_DPF((PVR_DBG_ERROR, "_PdumpAllocMMUContext: no free MMU context ids"));
+
+       return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
+{
+       if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
+       {
+               
+               gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
+               return PVRSRV_OK;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR, "_PdumpFreeMMUContext: MMU context ids invalid"));
+
+       return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+                                                               IMG_CHAR *pszMemSpace,
+                                                               IMG_UINT32 *pui32MMUContextID,
+                                                               IMG_UINT32 ui32MMUType,
+                                                               IMG_HANDLE hUniqueTag1,
+                                                               IMG_HANDLE hOSMemHandle, 
+                                                               IMG_VOID *pvPDCPUAddr)
+{
+       IMG_UINT8 *pui8LinAddr = (IMG_UINT8 *)pvPDCPUAddr;
+       IMG_CPU_PHYADDR sCpuPAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_UINT32 ui32MMUContextID;
+       PVRSRV_ERROR eError;
+
+       eError = _PdumpAllocMMUContext(&ui32MMUContextID);
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eError));
+               return eError;
+       }
+
+       
+       
+       sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
+       sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+       
+       sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) -1);
+
+       PDumpComment("Set MMU Context\r\n");
+       
+       PDumpComment("MMU :%s:v%d %d :%s:PA_%08X%08X\r\n",
+                                               pszMemSpace,
+                                               ui32MMUContextID,
+                                               ui32MMUType,
+                                               pszMemSpace,
+                                               (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+                                               sDevPAddr.uiAddr);
+
+       
+       *pui32MMUContextID = ui32MMUContextID;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+                                                               IMG_CHAR *pszMemSpace,
+                                                               IMG_UINT32 ui32MMUContextID,
+                                                               IMG_UINT32 ui32MMUType)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+       
+       PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
+       
+       PDumpComment("MMU :%s:v%d %d\r\n",
+                                               pszMemSpace,
+                                               ui32MMUContextID,
+                                               ui32MMUType);
+
+       eError = _PdumpFreeMMUContext(ui32MMUContextID);
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d", eError));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                        IMG_CHAR *pszFileName,
+                                                                IMG_UINT32 ui32FileOffset, 
+                                                                PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                                IMG_UINT32 uiAddr, 
+                                                                IMG_UINT32 ui32Size,
+                                                                IMG_UINT32 ui32PDumpFlags,
+                                                                IMG_HANDLE hUniqueTag)
+{
+       IMG_DEV_PHYADDR         sDevPAddr;
+       IMG_DEV_VIRTADDR        sDevVPageAddr;
+       IMG_UINT32                      ui32PageOffset;
+
+       PDUMP_GET_SCRIPT_STRING();
+
+       
+
+
+       ui32PageOffset = (IMG_UINT32)psMemInfo->pvLinAddrKM & psMMUAttrib->ui32DataPageMask;
+       
+       
+       sDevVPageAddr.uiAddr = uiAddr - ui32PageOffset;
+       
+       
+       BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+       
+       
+       sDevPAddr.uiAddr += ui32PageOffset;
+
+       PDumpOSBufprintf(hScript,
+                        ui32MaxLen,
+                        "SAB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+                        psMMUAttrib->sDevId.pszPDumpDevName,
+                        (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+                        sDevPAddr.uiAddr & ~psMMUAttrib->ui32DataPageMask,
+                        sDevPAddr.uiAddr & psMMUAttrib->ui32DataPageMask,
+                        ui32Size,
+                        ui32FileOffset,
+                        pszFileName);
+
+       PDumpOSWriteString2(hScript, ui32PDumpFlags);
+       
+       return PVRSRV_OK;       
+}
+
+PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR         *pszPDumpRegName,
+                                                         IMG_UINT32    ui32RegOffset,
+                                                         IMG_UINT32    ui32WPosVal,
+                                                         IMG_UINT32    ui32PacketSize,
+                                                         IMG_UINT32    ui32BufferSize,
+                                                         IMG_UINT32    ui32Flags)
+{
+       PDUMP_GET_SCRIPT_STRING();
+
+       PDumpOSBufprintf(hScript,
+                        ui32MaxLen,
+                        "CBP :%s:0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+                        pszPDumpRegName,
+                        ui32RegOffset,
+                        ui32WPosVal,
+                        ui32PacketSize,
+                        ui32BufferSize);
+       PDumpOSWriteString2(hScript, ui32Flags);
+       
+       return PVRSRV_OK;               
+}
+
+
+#include "syscommon.h"
+
+IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID)
+{
+       SYS_DATA                        *psSysData;
+       PVRSRV_DEVICE_NODE      *psThis;
+       PVR_DPF((PVR_DBG_WARNING, "PDump has connected."));
+       
+       
+       SysAcquireData(&psSysData);
+       
+       psThis = psSysData->psDeviceNodeList;
+       while (psThis)
+       {
+               if (psThis->pfnPDumpInitDevice)
+               {
+                       
+                       psThis->pfnPDumpInitDevice(psThis);
+               }
+               psThis = psThis->psNext;
+       }
+}
+
+IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+       IMG_UINT32      ui32BytesWritten = 0;
+       IMG_UINT32      ui32Off = 0;
+       PDBG_STREAM_CONTROL psCtrl = psStream->psCtrl;
+
+       
+       if ((ui32Flags & PDUMP_FLAGS_NEVER) != 0)
+       {
+               return ui32BCount;
+       }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+       if ( (_PDumpIsProcessActive() == IMG_FALSE ) &&
+                ((ui32Flags & PDUMP_FLAGS_PERSISTENT) == 0) )
+       {
+               return ui32BCount;
+       }
+#endif
+
+
+       if ( ((ui32Flags & PDUMP_FLAGS_PERSISTENT) != 0) && (psCtrl->bInitPhaseComplete) )
+       {
+       while (((IMG_UINT32) ui32BCount > 0) && (ui32BytesWritten != 0xFFFFFFFFU))
+       {
+                       
+
+                               
+                               ui32BytesWritten = PDumpOSDebugDriverWrite(     psStream,
+                                                                                                                       PDUMP_WRITE_MODE_PERSISTENT,
+                                                                                                                       &pui8Data[ui32Off], ui32BCount, 1, 0);
+
+                       if (ui32BytesWritten == 0)
+                       {
+                               PDumpOSReleaseExecution();
+                       }
+
+                       if (ui32BytesWritten != 0xFFFFFFFFU)
+                       {
+                               ui32Off += ui32BytesWritten;
+                               ui32BCount -= ui32BytesWritten;
+                       }
+                       else
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "DbgWrite: Failed to send persistent data"));
+                               if( (psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) != 0)
+                               {
+
+                                       PDumpSuspendKM();
+                               }
+                               return 0xFFFFFFFFU;
+                       }
+               }
+
+
+               ui32BCount = ui32Off; ui32Off = 0; ui32BytesWritten = 0;
+       }
+
+       while (((IMG_UINT32) ui32BCount > 0) && (ui32BytesWritten != 0xFFFFFFFFU))
+       {
+               if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
+               {
+                       
+
+                       if (((psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+                                (psCtrl->ui32Start == 0xFFFFFFFFU) &&
+                                (psCtrl->ui32End == 0xFFFFFFFFU) &&
+                                 psCtrl->bInitPhaseComplete)
+                       {
+                               ui32BytesWritten = ui32BCount;
+                       }
+                       else
+                       {
+                               ui32BytesWritten = PDumpOSDebugDriverWrite(     psStream, 
+                                                                                                                       PDUMP_WRITE_MODE_CONTINUOUS,
+                                                                                                                       &pui8Data[ui32Off], ui32BCount, 1, 0);
+                       }
+               }
+               else
+               {
+                       if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
+                       {
+                               IMG_UINT32      ui32DbgFlags;
+       
+                               ui32DbgFlags = 0;
+                               if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+                               {
+                                       ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+                               }
+       
+                               ui32BytesWritten = PDumpOSDebugDriverWrite(     psStream,
+                                                                                                                       PDUMP_WRITE_MODE_LASTFRAME,
+                                                                                                                       &pui8Data[ui32Off], ui32BCount, 1, ui32DbgFlags);
+                       }
+                       else
+                       {
+                               ui32BytesWritten = PDumpOSDebugDriverWrite(     psStream, 
+                                                                                                                       PDUMP_WRITE_MODE_BINCM,
+                                                                                                                       &pui8Data[ui32Off], ui32BCount, 1, 0);
+                       }
+               }
+
+               
+
+
+               if (ui32BytesWritten == 0)
+               {
+                       PDumpOSReleaseExecution();
+               }
+
+               if (ui32BytesWritten != 0xFFFFFFFFU)
+               {
+                       ui32Off += ui32BytesWritten;
+                       ui32BCount -= ui32BytesWritten;
+               }
+
+               
+       }
+
+
+       
+       return ui32BytesWritten;
+}
+
+
+
+#else  
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/perproc.c b/drivers/staging/mrst/pvr/services4/srvkm/common/perproc.c
new file mode 100644 (file)
index 0000000..25e5bb9
--- /dev/null
@@ -0,0 +1,323 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/sched.h>
+
+#include "services_headers.h"
+#include "resman.h"
+#include "handle.h"
+#include "perproc.h"
+#include "osperproc.h"
+#if defined(PERPROC_LIST)
+#include "lists.h"
+#endif
+#define        HASH_TAB_INIT_SIZE 32
+
+static HASH_TABLE *psHashTab = IMG_NULL;
+#if defined(PERPROC_LIST)
+static PVRSRV_PER_PROCESS_DATA *psPerProcList = IMG_NULL;
+#endif
+static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_ERROR eError;
+       IMG_UINTPTR_T uiPerProc;
+
+       PVR_ASSERT(psPerProc != IMG_NULL);
+
+       if (psPerProc == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID);
+       if (uiPerProc == 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
+
+               PVR_ASSERT(psPerProc->ui32PID == 0);
+       }
+       else
+       {
+               PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc);
+               PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
+       }
+#if defined(PERPROC_LIST)
+       List_PVRSRV_PER_PROCESS_DATA_Remove(psPerProc);
+       /*PVR_LOG(("MarkTu free perproce %d\n", psPerProc->ui32PID));*/
+#endif
+
+       if (psPerProc->psHandleBase != IMG_NULL)
+       {
+               eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError));
+                       return eError;
+               }
+       }
+
+
+       if (psPerProc->hPerProcData != IMG_NULL)
+       {
+               eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError));
+                       return eError;
+               }
+       }
+
+
+       eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
+       if (eError != PVRSRV_OK)
+       {
+                PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError));
+               return eError;
+       }
+
+       eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+               sizeof(*psPerProc),
+               psPerProc,
+               psPerProc->hBlockAlloc);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
+{
+       PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+       PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+       psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+       return psPerProc;
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32    ui32PID, IMG_UINT32 ui32Flags)
+{
+       PVRSRV_PER_PROCESS_DATA *psPerProc;
+       IMG_HANDLE hBlockAlloc;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+       psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+
+       if (psPerProc == IMG_NULL)
+       {
+
+               eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                                       sizeof(*psPerProc),
+                                                       (IMG_PVOID *)&psPerProc,
+                                                       &hBlockAlloc,
+                                                       "Per Process Data");
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError));
+                       return eError;
+               }
+               OSMemSet(psPerProc, 0, sizeof(*psPerProc));
+               psPerProc->hBlockAlloc = hBlockAlloc;
+
+               /*
+                * FIXME: using a hash to retrieve psPerProc makes not much
+                * sense. We always want to have this struct on the IOCTL path
+                * for the current task, so it'd be just a matter of storing
+                * it in the file private object. Until this is resolved and
+                * we get rid of this pid specific lookup make sure the above
+                * assumption holds.
+                */
+               WARN_ON(OSGetCurrentProcessIDKM() != ui32PID);
+               get_task_comm(psPerProc->name, current);
+
+               if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table"));
+                       eError = PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED;
+                       goto failure;
+               }
+               psPerProc->ui32PID = ui32PID;
+               psPerProc->ui32RefCount = 0;
+
+#if defined(PERPROC_LIST)
+               List_PVRSRV_PER_PROCESS_DATA_Insert(&psPerProcList, psPerProc);
+               /*PVR_LOG(("MarkTupsperproc %d\n", ui32PID));*/
+#endif
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+               if (ui32Flags == SRV_FLAGS_PDUMP_ACTIVE)
+               {
+                       psPerProc->bPDumpActive = IMG_TRUE;
+               }
+#else
+               PVR_UNREFERENCED_PARAMETER(ui32Flags);
+#endif
+
+
+               eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
+               if (eError != PVRSRV_OK)
+               {
+                        PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError));
+                       goto failure;
+               }
+
+
+               eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+                                                                  &psPerProc->hPerProcData,
+                                                                  psPerProc,
+                                                                  PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+                                                                  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError));
+                       goto failure;
+               }
+
+
+               eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError));
+                       goto failure;
+               }
+
+
+               eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError));
+                       goto failure;
+               }
+
+
+               eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager"));
+                       goto failure;
+               }
+       }
+
+       psPerProc->ui32RefCount++;
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
+                       ui32PID, psPerProc->ui32RefCount));
+
+       return eError;
+
+failure:
+       (IMG_VOID)FreePerProcessData(psPerProc);
+       return eError;
+}
+
+
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32     ui32PID)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+       PVR_ASSERT(psHashTab != IMG_NULL);
+
+       psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+       if (psPerProc == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u", ui32PID));
+       }
+       else
+       {
+               psPerProc->ui32RefCount--;
+               if (psPerProc->ui32RefCount == 0)
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: "
+                                       "Last close from process 0x%x received", ui32PID));
+
+
+                       PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
+
+
+                       eError = FreePerProcessData(psPerProc);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Error freeing per-process data"));
+                       }
+               }
+       }
+
+       eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)", eError));
+       }
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
+{
+       PVR_ASSERT(psHashTab == IMG_NULL);
+
+
+       psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
+       if (psHashTab == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: Couldn't create per-process data hash table"));
+               return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
+{
+
+       if (psHashTab != IMG_NULL)
+       {
+
+               HASH_Delete(psHashTab);
+               psHashTab = IMG_NULL;
+       }
+
+       return PVRSRV_OK;
+}
+
+#if defined(PERPROC_LIST)
+/*only used by PVRSRV_RESOURCE_PROFILING now*/
+PVRSRV_PER_PROCESS_DATA* PVRSRVPerProcessList(IMG_VOID)
+{
+       return  psPerProcList;
+}
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/power.c b/drivers/staging/mrst/pvr/services4/srvkm/common/power.c
new file mode 100644 (file)
index 0000000..6596d3e
--- /dev/null
@@ -0,0 +1,796 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pdump_km.h"
+
+#include "lists.h"
+
+static IMG_BOOL gbInitServerRunning = IMG_FALSE;
+static IMG_BOOL gbInitServerRan = IMG_FALSE;
+static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
+{
+
+       switch(eInitServerState)
+       {
+               case PVRSRV_INIT_SERVER_RUNNING:
+                       gbInitServerRunning     = bState;
+                       break;
+               case PVRSRV_INIT_SERVER_RAN:
+                       gbInitServerRan = bState;
+                       break;
+               case PVRSRV_INIT_SERVER_SUCCESSFUL:
+                       gbInitSuccessful = bState;
+                       break;
+               default:
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "PVRSRVSetInitServerState : Unknown state %x", eInitServerState));
+                       return PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE;
+       }
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+       IMG_BOOL        bReturnVal;
+
+       switch(eInitServerState)
+       {
+               case PVRSRV_INIT_SERVER_RUNNING:
+                       bReturnVal = gbInitServerRunning;
+                       break;
+               case PVRSRV_INIT_SERVER_RAN:
+                       bReturnVal = gbInitServerRan;
+                       break;
+               case PVRSRV_INIT_SERVER_SUCCESSFUL:
+                       bReturnVal = gbInitSuccessful;
+                       break;
+               default:
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "PVRSRVGetInitServerState : Unknown state %x", eInitServerState));
+                       bReturnVal = IMG_FALSE;
+       }
+
+       return bReturnVal;
+}
+
+static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
+{
+       return (IMG_BOOL)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32        ui32CallerID,
+                                                        IMG_BOOL       bSystemPowerEvent)
+{
+       PVRSRV_ERROR    eError;
+       SYS_DATA                *psSysData;
+       IMG_UINT32              ui32Timeout = 1000000;
+
+#if defined(SUPPORT_LMA)
+       
+       ui32Timeout *= 60;
+#endif 
+
+       SysAcquireData(&psSysData);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+       eError = SysPowerLockWrap(psSysData);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+#endif
+       do
+       {
+               eError = OSLockResource(&psSysData->sPowerStateChangeResource,
+                                                               ui32CallerID);
+               if (eError == PVRSRV_OK)
+               {
+                       break;
+               }
+               else if (ui32CallerID == ISR_ID)
+               {
+                       
+
+                       eError = PVRSRV_ERROR_RETRY;
+                       break;
+               }
+
+               OSWaitus(1);
+               ui32Timeout--;
+       } while (ui32Timeout > 0);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+       if (eError != PVRSRV_OK)
+       {
+               SysPowerLockUnwrap(psSysData);
+       }
+#endif
+        
+       if ((eError == PVRSRV_OK) &&
+               !bSystemPowerEvent &&
+               !_IsSystemStatePowered(psSysData->eCurrentPowerState))
+       {
+               
+               PVRSRVPowerUnlock(ui32CallerID);
+               eError = PVRSRV_ERROR_RETRY;
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32  ui32CallerID)
+{
+       OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID);
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+       SysPowerLockUnwrap(gpsSysData);
+#endif
+}
+
+
+static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+       PVRSRV_DEV_POWER_STATE  eNewDevicePowerState;
+       PVRSRV_ERROR                    eError;
+
+       
+       IMG_BOOL                                bAllDevices;
+       IMG_UINT32                              ui32DeviceIndex;
+       PVRSRV_DEV_POWER_STATE  eNewPowerState;
+
+       
+       bAllDevices = va_arg(va, IMG_BOOL);
+       ui32DeviceIndex = va_arg(va, IMG_UINT32);
+       eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+       if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+       {
+               eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+                                                       psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+               if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+               {
+                       if (psPowerDevice->pfnPrePower != IMG_NULL)
+                       {
+                               
+                               eError = psPowerDevice->pfnPrePower(psPowerDevice->hDevCookie,
+                                                                                                       eNewDevicePowerState,
+                                                                                                       psPowerDevice->eCurrentPowerState);
+                               if (eError != PVRSRV_OK)
+                               {
+                                       return eError;
+                               }
+                       }
+
+                       
+                       eError = SysDevicePrePowerState(psPowerDevice->ui32DeviceIndex,
+                                                                                       eNewDevicePowerState,
+                                                                                       psPowerDevice->eCurrentPowerState);
+                       if (eError != PVRSRV_OK)
+                       {
+                               return eError;
+                       }
+               }
+       }
+
+       return  PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL                              bAllDevices,
+                                                                                IMG_UINT32                             ui32DeviceIndex,
+                                                                                PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR            eError;
+       SYS_DATA                        *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       
+       eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+                                                                                                               &PVRSRVDevicePrePowerStateKM_AnyVaCb,
+                                                                                                               bAllDevices,
+                                                                                                               ui32DeviceIndex,
+                                                                                                               eNewPowerState);
+
+       return eError;
+}
+
+static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+       PVRSRV_DEV_POWER_STATE  eNewDevicePowerState;
+       PVRSRV_ERROR                    eError;
+
+       
+       IMG_BOOL                                bAllDevices;
+       IMG_UINT32                              ui32DeviceIndex;
+       PVRSRV_DEV_POWER_STATE  eNewPowerState;
+
+       
+       bAllDevices = va_arg(va, IMG_BOOL);
+       ui32DeviceIndex = va_arg(va, IMG_UINT32);
+       eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+       if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+       {
+               eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+                                                               psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+               if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+               {
+                       
+                       eError = SysDevicePostPowerState(psPowerDevice->ui32DeviceIndex,
+                                                                                        eNewDevicePowerState,
+                                                                                        psPowerDevice->eCurrentPowerState);
+                       if (eError != PVRSRV_OK)
+                       {
+                               return eError;
+                       }
+
+                       if (psPowerDevice->pfnPostPower != IMG_NULL)
+                       {
+                               
+                               eError = psPowerDevice->pfnPostPower(psPowerDevice->hDevCookie,
+                                                                                                        eNewDevicePowerState,
+                                                                                                        psPowerDevice->eCurrentPowerState);
+                               if (eError != PVRSRV_OK)
+                               {
+                                       return eError;
+                               }
+                       }
+
+                       psPowerDevice->eCurrentPowerState = eNewDevicePowerState;
+               }
+       }
+       return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL                                     bAllDevices,
+                                                                                 IMG_UINT32                            ui32DeviceIndex,
+                                                                                 PVRSRV_DEV_POWER_STATE        eNewPowerState)
+{
+       PVRSRV_ERROR            eError;
+       SYS_DATA                        *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       
+       eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+                                                                                                               &PVRSRVDevicePostPowerStateKM_AnyVaCb,
+                                                                                                               bAllDevices,
+                                                                                                               ui32DeviceIndex,
+                                                                                                               eNewPowerState);
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32                            ui32DeviceIndex,
+                                                                                PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                                                                IMG_UINT32                             ui32CallerID,
+                                                                                IMG_BOOL                               bRetainMutex)
+{
+       PVRSRV_ERROR    eError;
+       SYS_DATA                *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+       if(eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       #if defined(PDUMP)
+       if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+       {
+               
+
+
+
+               eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+               if(eError != PVRSRV_OK)
+               {
+                       goto Exit;
+               }
+
+               eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+
+               if (eError != PVRSRV_OK)
+               {
+                       goto Exit;
+               }
+
+               PDUMPSUSPEND();
+       }
+       #endif 
+
+       eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+       if(eError != PVRSRV_OK)
+       {
+               if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+               {
+                       PDUMPRESUME();
+               }
+               goto Exit;
+       }
+
+       eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+
+       if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+       {
+               PDUMPRESUME();
+       }
+
+Exit:
+
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError));
+       }
+
+       if (!bRetainMutex || (eError != PVRSRV_OK))
+       {
+               PVRSRVPowerUnlock(ui32CallerID);
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+       PVRSRV_ERROR                    eError;
+       SYS_DATA                                *psSysData;
+       PVRSRV_DEV_POWER_STATE  eNewDevicePowerState;
+
+       SysAcquireData(&psSysData);
+
+       
+       eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
+       if(eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       if (_IsSystemStatePowered(eNewSysPowerState) !=
+               _IsSystemStatePowered(psSysData->eCurrentPowerState))
+       {
+               if (_IsSystemStatePowered(eNewSysPowerState))
+               {
+                       
+                       eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+               }
+               else
+               {
+                       eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+               }
+
+               
+               eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+               if (eError != PVRSRV_OK)
+               {
+                       goto ErrorExit;
+               }
+       }
+
+       if (eNewSysPowerState != psSysData->eCurrentPowerState)
+       {
+               
+               eError = SysSystemPrePowerState(eNewSysPowerState);
+               if (eError != PVRSRV_OK)
+               {
+                       goto ErrorExit;
+               }
+       }
+
+       return eError;
+
+ErrorExit:
+
+       PVR_DPF((PVR_DBG_ERROR,
+                       "PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
+                       psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+       
+       psSysData->eFailedPowerState = eNewSysPowerState;
+
+       PVRSRVPowerUnlock(KERNEL_ID);
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+       PVRSRV_ERROR                    eError = PVRSRV_OK;
+       SYS_DATA                                *psSysData;
+       PVRSRV_DEV_POWER_STATE  eNewDevicePowerState;
+
+       SysAcquireData(&psSysData);
+
+       if (eNewSysPowerState != psSysData->eCurrentPowerState)
+       {
+               
+               eError = SysSystemPostPowerState(eNewSysPowerState);
+               if (eError != PVRSRV_OK)
+               {
+                       goto Exit;
+               }
+       }
+
+       if (_IsSystemStatePowered(eNewSysPowerState) !=
+               _IsSystemStatePowered(psSysData->eCurrentPowerState))
+       {
+               if (_IsSystemStatePowered(eNewSysPowerState))
+               {
+                       
+                       eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+               }
+               else
+               {
+                       eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+               }
+
+               
+               eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+               if (eError != PVRSRV_OK)
+               {
+                       goto Exit;
+               }
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK",
+                       psSysData->eCurrentPowerState, eNewSysPowerState));
+
+       psSysData->eCurrentPowerState = eNewSysPowerState;
+
+Exit:
+
+       PVRSRVPowerUnlock(KERNEL_ID);
+
+        
+       if (_IsSystemStatePowered(eNewSysPowerState) &&
+                       PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+       {
+               
+
+
+               PVRSRVScheduleDeviceCallbacks();
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+       PVRSRV_ERROR    eError;
+       SYS_DATA                *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       eError = PVRSRVSystemPrePowerStateKM(eNewSysPowerState);
+       if(eError != PVRSRV_OK)
+       {
+               goto ErrorExit;
+       }
+
+       eError = PVRSRVSystemPostPowerStateKM(eNewSysPowerState);
+       if(eError != PVRSRV_OK)
+       {
+               goto ErrorExit;
+       }
+
+       
+       psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       PVR_DPF((PVR_DBG_ERROR,
+                       "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
+                       psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+       
+       psSysData->eFailedPowerState = eNewSysPowerState;
+
+       return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32                                      ui32DeviceIndex,
+                                                                          PFN_PRE_POWER                                pfnPrePower,
+                                                                          PFN_POST_POWER                               pfnPostPower,
+                                                                          PFN_PRE_CLOCKSPEED_CHANGE    pfnPreClockSpeedChange,
+                                                                          PFN_POST_CLOCKSPEED_CHANGE   pfnPostClockSpeedChange,
+                                                                          IMG_HANDLE                                   hDevCookie,
+                                                                          PVRSRV_DEV_POWER_STATE               eCurrentPowerState,
+                                                                          PVRSRV_DEV_POWER_STATE               eDefaultPowerState)
+{
+       PVRSRV_ERROR            eError;
+       SYS_DATA                        *psSysData;
+       PVRSRV_POWER_DEV        *psPowerDevice;
+
+       if (pfnPrePower == IMG_NULL &&
+               pfnPostPower == IMG_NULL)
+       {
+               return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+       }
+
+       SysAcquireData(&psSysData);
+
+       eError = OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                                sizeof(PVRSRV_POWER_DEV),
+                                                (IMG_VOID **)&psPowerDevice, IMG_NULL,
+                                                "Power Device");
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+               return eError;
+       }
+
+       
+       psPowerDevice->pfnPrePower = pfnPrePower;
+       psPowerDevice->pfnPostPower = pfnPostPower;
+       psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
+       psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange;
+       psPowerDevice->hDevCookie = hDevCookie;
+       psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
+       psPowerDevice->eCurrentPowerState = eCurrentPowerState;
+       psPowerDevice->eDefaultPowerState = eDefaultPowerState;
+
+       
+       List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList), psPowerDevice);
+
+       return (PVRSRV_OK);
+}
+
+
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
+{
+       SYS_DATA                        *psSysData;
+       PVRSRV_POWER_DEV        *psPowerDev;
+
+       SysAcquireData(&psSysData);
+
+       
+       psPowerDev = (PVRSRV_POWER_DEV*)
+                                       List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+                                                                                                &MatchPowerDeviceIndex_AnyVaCb,
+                                                                                                ui32DeviceIndex);
+
+       if (psPowerDev)
+       {
+               List_PVRSRV_POWER_DEV_Remove(psPowerDev);
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV), psPowerDev, IMG_NULL);
+               
+       }
+
+       return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+{
+       SYS_DATA                        *psSysData;
+       PVRSRV_POWER_DEV        *psPowerDevice;
+
+       SysAcquireData(&psSysData);
+
+        
+       if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID) ||
+               OSIsResourceLocked(&psSysData->sPowerStateChangeResource, ISR_ID))
+       {
+               return IMG_FALSE;
+       }
+
+       psPowerDevice = (PVRSRV_POWER_DEV*)
+                                       List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+                                                                                                &MatchPowerDeviceIndex_AnyVaCb,
+                                                                                                ui32DeviceIndex);
+       return (psPowerDevice && (psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON))
+                       ? IMG_TRUE : IMG_FALSE;
+}
+
+
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32        ui32DeviceIndex,
+                                                                                        IMG_BOOL       bIdleDevice,
+                                                                                        IMG_VOID       *pvInfo)
+{
+       PVRSRV_ERROR            eError = PVRSRV_OK;
+       SYS_DATA                        *psSysData;
+       PVRSRV_POWER_DEV        *psPowerDevice;
+
+       PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+       SysAcquireData(&psSysData);
+
+       if (bIdleDevice)
+       {
+               
+               eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%x", eError));
+                       return eError;
+               }
+       }
+
+       
+       psPowerDevice = (PVRSRV_POWER_DEV*)
+                                       List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+                                                                                                &MatchPowerDeviceIndex_AnyVaCb,
+                                                                                                ui32DeviceIndex);
+
+       if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+       {
+                       eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
+                                                                                                                  bIdleDevice,
+                                                                                                                  psPowerDevice->eCurrentPowerState);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                               "PVRSRVDevicePreClockSpeedChange : Device %u failed, error:0x%x",
+                                               ui32DeviceIndex, eError));
+                       }
+       }
+
+       if (bIdleDevice && eError != PVRSRV_OK)
+       {
+               PVRSRVPowerUnlock(KERNEL_ID);
+       }
+
+       return eError;
+}
+
+
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32   ui32DeviceIndex,
+                                                                                 IMG_BOOL              bIdleDevice,
+                                                                                 IMG_VOID              *pvInfo)
+{
+       PVRSRV_ERROR            eError;
+       SYS_DATA                        *psSysData;
+       PVRSRV_POWER_DEV        *psPowerDevice;
+
+       PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+       SysAcquireData(&psSysData);
+
+       
+       psPowerDevice = (PVRSRV_POWER_DEV*)
+                                       List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+                                                                                                &MatchPowerDeviceIndex_AnyVaCb,
+                                                                                                ui32DeviceIndex);
+
+       if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+       {
+               eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie,
+                                                                                                               bIdleDevice,
+                                                                                                               psPowerDevice->eCurrentPowerState);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "PVRSRVDevicePostClockSpeedChange : Device %u failed, error:0x%x",
+                                       ui32DeviceIndex, eError));
+               }
+       }
+
+
+       if (bIdleDevice)
+       {
+               
+               PVRSRVPowerUnlock(KERNEL_ID);
+       }
+}
+
+#if 0
+/*
+ * PVRSRVPowerOnSystemWithDevice
+ *
+ * Description: Power on the System if it is off, but instead of powering all
+ * of the devices to their "default" state, only turn on the specified
+ * device index.
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerOnSystemWithDevice(IMG_UINT32  ui32DeviceIndex,
+                                          IMG_UINT32   ui32CallerID,
+                                          IMG_BOOL     bRetainMutex)
+{
+       PVRSRV_ERROR    eError;
+       SYS_DATA        *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       eError = PVRSRVPowerLock(ui32CallerID, IMG_TRUE);
+       if(eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+       if (eError != PVRSRV_OK)
+       {
+               goto ErrorExit;
+       }
+
+       if (!_IsSystemStatePowered(psSysData->eCurrentPowerState))
+       {
+               eError = SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE_D0);
+               if (eError != PVRSRV_OK)
+               {
+                       goto ErrorExit;
+               }
+
+               eError = SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE_D0);
+               if (eError != PVRSRV_OK)
+               {
+                       goto ErrorExit;
+               }
+               psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+       }
+
+       eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+       if (eError != PVRSRV_OK)
+       {
+               goto ErrorExit;
+       }
+
+ErrorExit:
+
+       if(eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "PVRSRVPowerOnSystemWithDevice : FAILED 0x%x", eError));
+       }
+
+       if (!bRetainMutex || (eError != PVRSRV_OK))
+       {
+               PVRSRVPowerUnlock(ui32CallerID);
+       }
+
+       return eError;
+}
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/pvrsrv.c b/drivers/staging/mrst/pvr/services4/srvkm/common/pvrsrv.c
new file mode 100644 (file)
index 0000000..631555b
--- /dev/null
@@ -0,0 +1,1291 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "sgx_mkif_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfokm.h"
+#include "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "deviceid.h"
+#include "ra.h"
+
+#include "pvrversion.h"
+
+#include "lists.h"
+
+IMG_UINT32     g_ui32InitFlags;
+
+#define                INIT_DATA_ENABLE_PDUMPINIT      0x1U
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
+{
+       SYS_DEVICE_ID* psDeviceWalker;
+       SYS_DEVICE_ID* psDeviceEnd;
+
+       psDeviceWalker = &psSysData->sDeviceID[0];
+       psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+       
+       while (psDeviceWalker < psDeviceEnd)
+       {
+               if (!psDeviceWalker->bInUse)
+               {
+                       psDeviceWalker->bInUse = IMG_TRUE;
+                       *pui32DevID = psDeviceWalker->uiID;
+                       return PVRSRV_OK;
+               }
+               psDeviceWalker++;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
+
+       
+       PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+       return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE;
+}
+
+
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
+{
+       SYS_DEVICE_ID* psDeviceWalker;
+       SYS_DEVICE_ID* psDeviceEnd;
+
+       psDeviceWalker = &psSysData->sDeviceID[0];
+       psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+       
+       while (psDeviceWalker < psDeviceEnd)
+       {
+               
+               if      (
+                               (psDeviceWalker->uiID == ui32DevID) &&
+                               (psDeviceWalker->bInUse)
+                       )
+               {
+                       psDeviceWalker->bInUse = IMG_FALSE;
+                       return PVRSRV_OK;
+               }
+               psDeviceWalker++;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
+
+       
+       PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+       return PVRSRV_ERROR_INVALID_DEVICEID;
+}
+
+
+#ifndef ReadHWReg
+IMG_EXPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+       return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset);
+}
+#endif
+
+
+#ifndef WriteHWReg
+IMG_EXPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+       PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%x, Offset: %x, Value %x",
+                       (IMG_UINTPTR_T)pvLinRegBaseAddr,ui32Offset,ui32Value));
+
+       *(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+}
+#endif
+
+
+#ifndef WriteHWRegs
+IMG_EXPORT
+IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
+{
+       while (ui32Count)
+       {
+               WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal);
+               psHWRegs++;
+               ui32Count--;
+       }
+}
+#endif
+
+static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+       IMG_UINT *pui32DevCount;
+       PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
+
+       pui32DevCount = va_arg(va, IMG_UINT*);
+       ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**);
+
+       if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
+       {
+               *(*ppsDevIdList) = psDeviceNode->sDevId;
+               (*ppsDevIdList)++;
+               (*pui32DevCount)++;
+       }
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+                                                                                                  PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
+{
+       SYS_DATA                        *psSysData;
+       IMG_UINT32                      i;
+
+       if (!pui32NumDevices || !psDevIdList)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       SysAcquireData(&psSysData);
+
+       
+
+       for (i=0; i<PVRSRV_MAX_DEVICES; i++)
+       {
+               psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+       }
+
+       
+       *pui32NumDevices = 0;
+
+       
+
+
+
+       List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+                                                                          &PVRSRVEnumerateDevicesKM_ForEachVaCb,
+                                                                          pui32NumDevices,
+                                                                          &psDevIdList);
+
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
+{
+       PVRSRV_ERROR    eError;
+
+       
+       eError = ResManInit();
+       if (eError != PVRSRV_OK)
+       {
+               goto Error;
+       }
+
+       eError = PVRSRVPerProcessDataInit();
+       if(eError != PVRSRV_OK)
+       {
+               goto Error;
+       }
+
+       
+       eError = PVRSRVHandleInit();
+       if(eError != PVRSRV_OK)
+       {
+               goto Error;
+       }
+
+       
+       eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
+       if (eError != PVRSRV_OK)
+       {
+               goto Error;
+       }
+
+       
+       psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+       psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+       
+       if(OSAllocMem( PVRSRV_PAGEABLE_SELECT,
+                                        sizeof(PVRSRV_EVENTOBJECT) ,
+                                        (IMG_VOID **)&psSysData->psGlobalEventObject, 0,
+                                        "Event Object") != PVRSRV_OK)
+       {
+
+               goto Error;
+       }
+
+       if(OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject) != PVRSRV_OK)
+       {
+               goto Error;
+       }
+
+       
+       PDUMPINIT();
+       g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
+
+       return eError;
+
+Error:
+       PVRSRVDeInit(psSysData);
+       return eError;
+}
+
+
+
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
+{
+       PVRSRV_ERROR    eError;
+
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+
+       if (psSysData == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
+               return;
+       }
+
+       
+       if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
+       {
+               PDUMPDEINIT();
+       }
+       
+       
+       if(psSysData->psGlobalEventObject)
+       {
+               OSEventObjectDestroy(psSysData->psGlobalEventObject);
+               OSFreeMem( PVRSRV_PAGEABLE_SELECT,
+                                                sizeof(PVRSRV_EVENTOBJECT),
+                                                psSysData->psGlobalEventObject,
+                                                0);
+               psSysData->psGlobalEventObject = IMG_NULL;
+       }
+
+       eError = PVRSRVHandleDeInit();
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
+       }
+
+       eError = PVRSRVPerProcessDataDeInit();
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
+       }
+
+       ResManDeInit();
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+                                                                                         PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+                                                                                         IMG_UINT32 ui32SOCInterruptBit,
+                                                                                         IMG_UINT32 *pui32DeviceIndex)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+
+       
+       if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_DEVICE_NODE),
+                                        (IMG_VOID **)&psDeviceNode, IMG_NULL,
+                                        "Device Node") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
+               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+       }
+       OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+       eError = pfnRegisterDevice(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                       sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+               
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
+               return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
+       }
+
+       
+
+
+
+
+       psDeviceNode->ui32RefCount = 1;
+       psDeviceNode->psSysData = psSysData;
+       psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
+
+       
+       AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+
+       
+       List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+       
+       *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
+{
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       SYS_DATA                        *psSysData;
+       PVRSRV_ERROR            eError;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
+
+       SysAcquireData(&psSysData);
+
+       
+       psDeviceNode = (PVRSRV_DEVICE_NODE*)
+                                        List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                                       &MatchDeviceKM_AnyVaCb,
+                                                                                                       ui32DevIndex,
+                                                                                                       IMG_TRUE);
+       if(!psDeviceNode)
+       {
+               
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
+               return PVRSRV_ERROR_INIT_FAILURE;
+       }
+       PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+       
+
+       eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
+               return eError;
+       }
+
+       
+       if(psDeviceNode->pfnInitDevice != IMG_NULL)
+       {
+               eError = psDeviceNode->pfnInitDevice(psDeviceNode);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call"));
+                       return eError;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+       eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+                                                                                PVRSRV_DEV_POWER_STATE_DEFAULT,
+                                                                                KERNEL_ID, IMG_FALSE);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+       }
+       return eError;
+}
+
+static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+       eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+       }
+       return eError;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
+{
+       SYS_DATA                *psSysData;
+       PVRSRV_ERROR            eError;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+       SysAcquireData(&psSysData);
+
+       if (bInitSuccessful)
+       {
+               eError = SysFinalise();
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError));
+                       return eError;
+               }
+
+               
+               eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+                                                                                                               &PVRSRVFinaliseSystem_SetPowerState_AnyCb);
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+
+               
+               eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+                                                                                                       &PVRSRVFinaliseSystem_CompatCheck_AnyCb);
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+       }
+
+       
+
+
+
+       PDUMPENDINITPHASE();
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       
+       if (psDeviceNode->pfnInitDeviceCompatCheck)
+               return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+       else
+               return PVRSRV_OK;
+}
+
+static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+       PVRSRV_DEVICE_TYPE eDeviceType;
+       IMG_UINT32 ui32DevIndex;
+
+       eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
+       ui32DevIndex = va_arg(va, IMG_UINT32);
+
+       if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
+               psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
+               (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
+                psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
+       {
+               return psDeviceNode;
+       }
+       else
+       {
+               return IMG_NULL;
+       }
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32                        ui32DevIndex,
+                                                                                                        PVRSRV_DEVICE_TYPE     eDeviceType,
+                                                                                                        IMG_HANDLE                     *phDevCookie)
+{
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       SYS_DATA                        *psSysData;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+       SysAcquireData(&psSysData);
+
+       
+       psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                               &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
+                                                                                               eDeviceType,
+                                                                                               ui32DevIndex);
+
+
+       if (!psDeviceNode)
+       {
+               
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
+               return PVRSRV_ERROR_INIT_FAILURE;
+       }
+
+       PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+       
+       if (phDevCookie)
+       {
+               *phDevCookie = (IMG_HANDLE)psDeviceNode;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
+{
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       SYS_DATA                        *psSysData;
+       PVRSRV_ERROR            eError;
+
+       SysAcquireData(&psSysData);
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE*)
+                                        List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                                       &MatchDeviceKM_AnyVaCb,
+                                                                                                       ui32DevIndex,
+                                                                                                       IMG_TRUE);
+
+       if (!psDeviceNode)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex));
+               return PVRSRV_ERROR_DEVICEID_NOT_FOUND;
+       }
+
+       
+
+       eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+                                                                                PVRSRV_DEV_POWER_STATE_OFF,
+                                                                                KERNEL_ID,
+                                                                                IMG_FALSE);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
+               return eError;
+       }
+
+       
+
+       eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
+                                                                        RESMAN_CRITERIA_RESTYPE,
+                                                                        RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+                                                                        IMG_NULL, 0);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
+               return eError;
+       }
+
+       
+
+       if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
+       {
+               eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
+                       return eError;
+               }
+       }
+
+       
+
+       PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
+       psDeviceNode->hResManContext = IMG_NULL;
+
+       
+       List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+       
+       (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                               sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+       
+
+       return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
+                                                                                 IMG_UINT32 ui32Value,
+                                                                                 IMG_UINT32 ui32Mask,
+                                                                                 IMG_UINT32                    ui32Timeoutus,
+                                                                                 IMG_UINT32                    ui32PollPeriodus,
+                                                                                 IMG_BOOL                              bAllowPreemption)
+{
+       {
+               IMG_UINT32      ui32ActualValue = 0xFFFFFFFFU;
+
+               if (bAllowPreemption)
+               {
+                       PVR_ASSERT(ui32PollPeriodus >= 1000);
+               }
+
+                
+               LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
+               {
+                       ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
+                       if(ui32ActualValue == ui32Value)
+                       {
+                               return PVRSRV_OK;
+                       }
+
+                       if (bAllowPreemption)
+                       {
+                               OSSleepms(ui32PollPeriodus / 1000);
+                       }
+                       else
+                       {
+                               OSWaitus(ui32PollPeriodus);
+                       }
+               } END_LOOP_UNTIL_TIMEOUT();
+       
+               PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
+                               ui32Value, ui32ActualValue, ui32Mask));
+       }
+
+       return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+       IMG_CHAR **ppszStr;
+       IMG_UINT32 *pui32StrLen;
+       IMG_UINT32 ui32Mode;
+       PVRSRV_ERROR (*pfnGetStats)(RA_ARENA *, IMG_CHAR **, IMG_UINT32 *);
+
+       ppszStr = va_arg(va, IMG_CHAR**);
+       pui32StrLen = va_arg(va, IMG_UINT32*);
+       ui32Mode = va_arg(va, IMG_UINT32);
+
+       
+       switch(ui32Mode)
+       {
+               case PVRSRV_MISC_INFO_MEMSTATS_PRESENT:
+                       pfnGetStats = &RA_GetStats;
+                       break;
+               case PVRSRV_MISC_INFO_FREEMEM_PRESENT:
+                       pfnGetStats = &RA_GetStatsFreeMem;
+                       break;
+               default:
+                       return;
+       }
+
+       if(psBMHeap->pImportArena)
+       {
+               pfnGetStats(psBMHeap->pImportArena,
+                                       ppszStr,
+                                       pui32StrLen);
+       }
+
+       if(psBMHeap->pVMArena)
+       {
+               pfnGetStats(psBMHeap->pVMArena,
+                                       ppszStr,
+                                       pui32StrLen);
+       }
+}
+
+static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
+{
+
+       IMG_UINT32 *pui32StrLen;
+       IMG_INT32 *pi32Count;
+       IMG_CHAR **ppszStr;
+       IMG_UINT32 ui32Mode;
+
+       pui32StrLen = va_arg(va, IMG_UINT32*);
+       pi32Count = va_arg(va, IMG_INT32*);
+       ppszStr = va_arg(va, IMG_CHAR**);
+       ui32Mode = va_arg(va, IMG_UINT32);
+
+       CHECK_SPACE(*pui32StrLen);
+       *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n",
+                                                       (IMG_HANDLE)psBMContext);
+       UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+       List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
+                                                       &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+                                                       ppszStr,
+                                                       pui32StrLen,
+                                                       ui32Mode);
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+       IMG_UINT32 *pui32StrLen;
+       IMG_INT32 *pi32Count;
+       IMG_CHAR **ppszStr;
+       IMG_UINT32 ui32Mode;
+
+       pui32StrLen = va_arg(va, IMG_UINT32*);
+       pi32Count = va_arg(va, IMG_INT32*);
+       ppszStr = va_arg(va, IMG_CHAR**);
+       ui32Mode = va_arg(va, IMG_UINT32);
+
+       CHECK_SPACE(*pui32StrLen);
+       *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
+       UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+       
+       if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+       {
+               CHECK_SPACE(*pui32StrLen);
+               *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n");
+               UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+               List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap,
+                                                               &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+                                                               ppszStr,
+                                                               pui32StrLen,
+                                                               ui32Mode);
+       }
+
+       
+       return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
+                                                                                               &PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
+                                                                                               pui32StrLen,
+                                                                                               pi32Count,
+                                                                                               ppszStr,
+                                                                                               ui32Mode);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
+{
+       SYS_DATA *psSysData;
+
+       if(!psMiscInfo)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psMiscInfo->ui32StatePresent = 0;
+
+       
+       if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
+                                                                               |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
+                                                                               |PVRSRV_MISC_INFO_MEMSTATS_PRESENT
+                                                                               |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
+                                                                               |PVRSRV_MISC_INFO_DDKVERSION_PRESENT
+                                                                               |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
+                                                                               |PVRSRV_MISC_INFO_RESET_PRESENT
+                                                                               |PVRSRV_MISC_INFO_FREEMEM_PRESENT))
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       SysAcquireData(&psSysData);
+
+       
+       if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
+               (psSysData->pvSOCTimerRegisterKM != IMG_NULL))
+       {
+               psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
+               psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
+               psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
+       }
+       else
+       {
+               psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
+               psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
+       }
+
+       
+       if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
+               (psSysData->pvSOCClockGateRegsBase != IMG_NULL))
+       {
+               psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
+               psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
+               psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
+       }
+
+       
+       if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
+               (psMiscInfo->pszMemoryStr != IMG_NULL))
+       {
+               RA_ARENA                        **ppArena;
+               IMG_CHAR                        *pszStr;
+               IMG_UINT32                      ui32StrLen;
+               IMG_INT32                       i32Count;
+
+               pszStr = psMiscInfo->pszMemoryStr;
+               ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+               psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
+
+               
+               ppArena = &psSysData->apsLocalDevMemArena[0];
+               while(*ppArena)
+               {
+                       CHECK_SPACE(ui32StrLen);
+                       i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
+                       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+                       RA_GetStats(*ppArena,
+                                                       &pszStr,
+                                                       &ui32StrLen);
+                       
+                       ppArena++;
+               }
+
+               
+               
+               List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+                                                                                                       &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+                                                                                                       &ui32StrLen,
+                                                                                                       &i32Count,
+                                                                                                       &pszStr,
+                                                                                                       PVRSRV_MISC_INFO_MEMSTATS_PRESENT);
+
+               
+               i32Count = OSSNPrintf(pszStr, 100, "\n");
+               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+       }
+
+       
+       if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT)
+               && psMiscInfo->pszMemoryStr)
+       {
+               IMG_CHAR                        *pszStr;
+               IMG_UINT32                      ui32StrLen;
+               IMG_INT32                       i32Count;
+               
+               pszStr = psMiscInfo->pszMemoryStr;
+               ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+  
+               psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;
+
+               
+               List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+                                                                                                       &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+                                                                                                       &ui32StrLen,
+                                                                                                       &i32Count,
+                                                                                                       &pszStr,
+                                                                                                       PVRSRV_MISC_INFO_FREEMEM_PRESENT);
+               
+               i32Count = OSSNPrintf(pszStr, 100, "\n");
+               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+       }
+
+       if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
+               (psSysData->psGlobalEventObject != IMG_NULL))
+       {
+               psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
+               psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
+       }
+
+       
+
+       if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
+               && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
+               && (psMiscInfo->pszMemoryStr != IMG_NULL))
+       {
+               IMG_CHAR        *pszStr;
+               IMG_UINT32      ui32StrLen;
+               IMG_UINT32      ui32LenStrPerNum = 12; 
+               IMG_INT32       i32Count;
+               PVRSRV_SGXDEV_INFO              *sgx_dev_info;
+               PVRSRV_SGX_MISCINFO_INFO        *sgx_misc_info;
+               PVRSRV_SGX_MISCINFO_FEATURES    *sgx_features;
+               unsigned long                   fw_ver;
+               IMG_INT i;
+               psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
+
+               /*
+                * Since the kernel driver has already made sure that the
+                * firmware version is supported by the kernel driver in
+                * SGXDevInitCompatCheck, it's redundant for the user space
+                * part to perform the same check. In order to support older
+                * user space libraries where this check hasn't yet been removed,
+                * simply report the version of the downloaded firmware which
+                * will result in an exact match in user space.
+                */
+               sgx_dev_info = pvr_get_sgx_dev_info();
+               if (!sgx_dev_info || !sgx_dev_info->psKernelSGXMiscMemInfo ||
+                   !sgx_dev_info->psKernelSGXMiscMemInfo->pvLinAddrKM)
+                       return PVRSRV_ERROR_INVALID_DEVICE;
+
+               sgx_misc_info = sgx_dev_info->psKernelSGXMiscMemInfo->pvLinAddrKM;
+               sgx_features = &sgx_misc_info->sSGXFeatures;
+               fw_ver = sgx_features->ui32DDKVersion;
+
+               psMiscInfo->aui32DDKVersion[0] = PVR_FW_VER_MAJOR(fw_ver);
+               psMiscInfo->aui32DDKVersion[1] = PVR_FW_VER_MINOR(fw_ver);
+               psMiscInfo->aui32DDKVersion[2] = PVR_FW_VER_BRANCH(fw_ver);
+               psMiscInfo->aui32DDKVersion[3] = sgx_features->ui32DDKBuild;
+
+               pszStr = psMiscInfo->pszMemoryStr;
+               ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+               for (i=0; i<4; i++)
+               {
+                       if (ui32StrLen < ui32LenStrPerNum)
+                       {
+                               return PVRSRV_ERROR_INVALID_PARAMS;
+                       }
+
+                       i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]);
+                       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+                       if (i != 3)
+                       {
+                               i32Count = OSSNPrintf(pszStr, 2, ".");
+                               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+                       }
+               }
+       }
+
+       if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL)
+       {
+               if(psMiscInfo->sCacheOpCtl.bDeferOp)
+               {
+                       
+                       psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
+               }
+               else
+               {
+                       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+                       PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+                       if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
+                                                "Ignoring non-deferred cache op with no meminfo"));
+                               return PVRSRV_ERROR_INVALID_PARAMS;
+                       }
+
+                       if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
+                                                "Deferred cache op is pending. It is unlikely you want "
+                                                "to combine deferred cache ops with immediate ones"));
+                       }
+
+                       
+                       psPerProc = PVRSRVFindPerProcessData();
+
+                       if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                                                 (IMG_PVOID *)&psKernelMemInfo,
+                                                                 psMiscInfo->sCacheOpCtl.u.psKernelMemInfo,
+                                                                 PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
+                                                "Can't find kernel meminfo"));
+                               return PVRSRV_ERROR_INVALID_PARAMS;
+                       }
+
+                       if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+                       {
+                               if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+                                                                                  psMiscInfo->sCacheOpCtl.pvBaseVAddr,
+                                                                                  psMiscInfo->sCacheOpCtl.ui32Length))
+                               {
+                                       return PVRSRV_ERROR_CACHEOP_FAILED;
+                               }
+                       }
+                       else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+                       {
+                               if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+                                                                                  psMiscInfo->sCacheOpCtl.pvBaseVAddr,
+                                                                                  psMiscInfo->sCacheOpCtl.ui32Length))
+                               {
+                                       return PVRSRV_ERROR_CACHEOP_FAILED;
+                               }
+                       }
+               }
+       }
+
+#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
+       if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
+       {
+               PVR_LOG(("User requested OS reset"));
+               OSPanic();
+       }
+#endif 
+
+       return PVRSRV_OK;
+}
+
+
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       SYS_DATA                        *psSysData;
+       IMG_BOOL                        bStatus = IMG_FALSE;
+       IMG_UINT32                      ui32InterruptSource;
+
+       if(!psDeviceNode)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
+               goto out;
+       }
+       psSysData = psDeviceNode->psSysData;
+
+       
+       ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
+       if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+       {
+               if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+               {
+                       bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData);
+               }
+
+               SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit);
+       }
+
+out:
+       return bStatus;
+}
+
+static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+
+       IMG_BOOL *pbStatus;
+       IMG_UINT32 *pui32InterruptSource;
+       IMG_UINT32 *pui32ClearInterrupts;
+
+       pbStatus = va_arg(va, IMG_BOOL*);
+       pui32InterruptSource = va_arg(va, IMG_UINT32*);
+       pui32ClearInterrupts = va_arg(va, IMG_UINT32*);
+
+
+       if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+       {
+               if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+               {
+                       if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
+                       {
+                               
+                               *pbStatus = IMG_TRUE;
+                       }
+                       
+                       *pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
+               }
+       }
+}
+
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA                        *psSysData = pvSysData;
+       IMG_BOOL                        bStatus = IMG_FALSE;
+       IMG_UINT32                      ui32InterruptSource;
+       IMG_UINT32                      ui32ClearInterrupts = 0;
+       if(!psSysData)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+       }
+       else
+       {
+               
+               ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
+
+               
+               if(ui32InterruptSource)
+               {
+                       
+                       List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+                                                                                               &PVRSRVSystemLISR_ForEachVaCb,
+                                                                                               &bStatus,
+                                                                                               &ui32InterruptSource,
+                                                                                               &ui32ClearInterrupts);
+
+                       SysClearInterrupts(psSysData, ui32ClearInterrupts);
+               }
+       }
+       return bStatus;
+}
+
+
+static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       if(psDeviceNode->pfnDeviceMISR != IMG_NULL)
+       {
+               (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData);
+       }
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA                        *psSysData = pvSysData;
+       if(!psSysData)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
+               return;
+       }
+
+       
+       List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+                                                                       &PVRSRVMISR_ForEachCb);
+
+       
+       if (PVRSRVProcessQueues(ISR_ID, IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
+       {
+               PVRSRVProcessQueues(ISR_ID, IMG_FALSE);
+       }
+
+       
+       if (psSysData->psGlobalEventObject)
+       {
+               IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+               if(hOSEventKM)
+               {
+                       OSEventObjectSignal(hOSEventKM);
+               }
+       }
+
+       PVRSRVCheckPendingSyncs();
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32      ui32PID, IMG_UINT32 ui32Flags)
+{
+       return PVRSRVPerProcessDataConnect(ui32PID, ui32Flags);
+}
+
+
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32       ui32PID)
+{
+       PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
+                                                                                                               IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
+{
+       IMG_SIZE_T         uiBytesSaved = 0;
+       IMG_PVOID          pvLocalMemCPUVAddr;
+       RA_SEGMENT_DETAILS sSegDetails;
+
+       if (hArena == IMG_NULL)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       sSegDetails.uiSize = 0;
+       sSegDetails.sCpuPhyAddr.uiAddr = 0;
+       sSegDetails.hSegment = 0;
+
+       
+       while (RA_GetNextLiveSegment(hArena, &sSegDetails))
+       {
+               if (pbyBuffer == IMG_NULL)
+               {
+                       
+                       uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+               }
+               else
+               {
+                       if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize)
+                       {
+                               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+                       }
+
+                       PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize));
+
+                       
+                       pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
+                                                                       sSegDetails.uiSize,
+                                                                       PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                       IMG_NULL);
+                       if (pvLocalMemCPUVAddr == IMG_NULL)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
+                               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+                       }
+
+                       if (bSave)
+                       {
+                               
+                               OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
+                               pbyBuffer += sizeof(sSegDetails.uiSize);
+
+                               OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize);
+                               pbyBuffer += sSegDetails.uiSize;
+                       }
+                       else
+                       {
+                               IMG_UINT32 uiSize;
+                               
+                               OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
+
+                               if (uiSize != sSegDetails.uiSize)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error"));
+                               }
+                               else
+                               {
+                                       pbyBuffer += sizeof(sSegDetails.uiSize);
+
+                                       OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize);
+                                       pbyBuffer += sSegDetails.uiSize;
+                               }
+                       }
+
+
+                       uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+
+                       OSUnMapPhysToLin(pvLocalMemCPUVAddr,
+                                    sSegDetails.uiSize,
+                                    PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                    IMG_NULL);
+               }
+       }
+
+       if (pbyBuffer == IMG_NULL)
+       {
+               *puiBufSize = uiBytesSaved;
+       }
+
+       return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
+{ 
+#include "pvrsrv_errors.h"
+}
+
+static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+       {
+               
+               (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+       }
+}
+
+IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID)
+{
+       SYS_DATA                                *psSysData;
+       SysAcquireData(&psSysData);
+
+       
+       List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+                                                                       &PVRSRVCommandCompleteCallbacks_ForEachCb);
+}
+
+IMG_EXPORT
+IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID)
+{
+       PVRSRVScheduleDeviceCallbacks();
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/queue.c b/drivers/staging/mrst/pvr/services4/srvkm/common/queue.c
new file mode 100644 (file)
index 0000000..943490e
--- /dev/null
@@ -0,0 +1,1078 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "lists.h"
+#include "pvr_trace_cmd.h"
+
+
+#define DC_NUM_COMMANDS_PER_TYPE               1
+
+typedef struct _DEVICE_COMMAND_DATA_
+{
+       PFN_CMD_PROC                    pfnCmdProc;
+       PCOMMAND_COMPLETE_DATA  apsCmdCompleteData[DC_NUM_COMMANDS_PER_TYPE];
+       IMG_UINT32                              ui32CCBOffset;
+} DEVICE_COMMAND_DATA;
+
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#include "proc.h"
+
+void ProcSeqShowQueue(struct seq_file *sfile,void* el)
+{
+       PVRSRV_QUEUE_INFO *psQueue = (PVRSRV_QUEUE_INFO*)el;
+       IMG_INT cmds = 0;
+       IMG_SIZE_T ui32ReadOffset;
+       IMG_SIZE_T ui32WriteOffset;
+       PVRSRV_COMMAND *psCmd;
+
+       if(el == PVR_PROC_SEQ_START_TOKEN)
+       {
+               seq_printf( sfile,
+                                       "Command Queues\n"
+                                       "Queue    CmdPtr      Pid Command Size DevInd  DSC  SSC  #Data ...\n");
+               return;
+       }
+
+       ui32ReadOffset = psQueue->ui32ReadOffset;
+       ui32WriteOffset = psQueue->ui32WriteOffset;
+
+       while (ui32ReadOffset != ui32WriteOffset)
+       {
+               psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
+
+               seq_printf(sfile, "%x %x  %5u  %6u  %3u  %5u   %2u   %2u    %3u  \n",
+                                                       (IMG_UINTPTR_T)psQueue,
+                                                       (IMG_UINTPTR_T)psCmd,
+                                                       psCmd->ui32ProcessID,
+                                                       psCmd->CommandType,
+                                                       psCmd->ui32CmdSize,
+                                                       psCmd->ui32DevIndex,
+                                                       psCmd->ui32DstSyncCount,
+                                                       psCmd->ui32SrcSyncCount,
+                                                       psCmd->ui32DataSize);
+               
+               ui32ReadOffset += psCmd->ui32CmdSize;
+               ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+               cmds++;
+       }
+
+       if (cmds == 0)
+       {
+               seq_printf(sfile, "%x <empty>\n", (IMG_UINTPTR_T)psQueue);
+       }
+}
+
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
+{
+       PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+       SYS_DATA *psSysData;
+
+       PVR_UNREFERENCED_PARAMETER(sfile);
+
+       if(!off)
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+
+       psSysData = SysAcquireDataNoCheck();
+       if (psSysData != IMG_NULL)
+       {
+               for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM);
+       }
+
+       return psQueue;
+}
+#endif 
+
+#define GET_SPACE_IN_CMDQ(psQueue)                                                                             \
+       ((((psQueue)->ui32ReadOffset - (psQueue)->ui32WriteOffset)                              \
+       + ((psQueue)->ui32QueueSize - 1)) & ((psQueue)->ui32QueueSize - 1))
+
+#define UPDATE_QUEUE_WOFF(psQueue, ui32Size)                                                   \
+       (psQueue)->ui32WriteOffset = ((psQueue)->ui32WriteOffset + (ui32Size))  \
+       & ((psQueue)->ui32QueueSize - 1);
+
+#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending)                                 \
+       ((ui32OpsComplete) >= (ui32OpsPending))
+
+
+static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
+                                                                        IMG_UINT32                             i,
+                                                                        IMG_BOOL                               bIsSrc)
+{
+       PVRSRV_SYNC_OBJECT      *psSyncObject;
+
+       psSyncObject = bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->psDstSync;
+
+       if (psCmdCompleteData->bInUse)
+       {
+               PVR_LOG(("\t%s %u: ROC DevVAddr:0x%X ROP:0x%x ROC:0x%x, WOC DevVAddr:0x%X WOP:0x%x WOC:0x%x",
+                               bIsSrc ? "SRC" : "DEST", i,
+                               psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+                               psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending,
+                               psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete,
+                               psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+                               psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
+                               psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete))
+       }
+       else
+       {
+               PVR_LOG(("\t%s %u: (Not in use)", bIsSrc ? "SRC" : "DEST", i))
+       }
+}
+
+
+static IMG_VOID QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+       {
+               IMG_UINT32                              ui32CmdCounter, ui32SyncCounter;
+               SYS_DATA                *psSysData;
+               DEVICE_COMMAND_DATA             *psDeviceCommandData;
+               PCOMMAND_COMPLETE_DATA  psCmdCompleteData;
+
+               SysAcquireData(&psSysData);
+
+               psDeviceCommandData = psSysData->apsDeviceCommandData[psDeviceNode->sDevId.ui32DeviceIndex];
+
+               if (psDeviceCommandData != IMG_NULL)
+               {
+                       for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+                       {
+                               psCmdCompleteData = psDeviceCommandData[DC_FLIP_COMMAND].apsCmdCompleteData[ui32CmdCounter];
+
+                               PVR_LOG(("Flip Command Complete Data %u for display device %u:",
+                                               ui32CmdCounter, psDeviceNode->sDevId.ui32DeviceIndex))
+
+                               for (ui32SyncCounter = 0;
+                                        ui32SyncCounter < psCmdCompleteData->ui32SrcSyncCount;
+                                        ui32SyncCounter++)
+                               {
+                                       QueueDumpCmdComplete(psCmdCompleteData, ui32SyncCounter, IMG_TRUE);
+                               }
+
+                               for (ui32SyncCounter = 0;
+                                        ui32SyncCounter < psCmdCompleteData->ui32DstSyncCount;
+                                        ui32SyncCounter++)
+                               {
+                                       QueueDumpCmdComplete(psCmdCompleteData, ui32SyncCounter, IMG_FALSE);
+                               }
+                       }
+               }
+               else
+               {
+                       PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex))
+               }
+       }
+}
+
+
+IMG_VOID QueueDumpDebugInfo(IMG_VOID)
+{
+       SYS_DATA        *psSysData;
+       SysAcquireData(&psSysData);
+       List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, &QueueDumpDebugInfo_ForEachCb);
+}
+
+
+static IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
+{
+       IMG_SIZE_T ui32Temp, ui32Result = 1;
+
+       if(!ui32Value)
+               return 0;
+
+       ui32Temp = ui32Value - 1;
+       while(ui32Temp)
+       {
+               ui32Result <<= 1;
+               ui32Temp >>= 1;
+       }
+
+       return ui32Result;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+                                                                                                        PVRSRV_QUEUE_INFO **ppsQueueInfo)
+{
+       PVRSRV_QUEUE_INFO       *psQueueInfo;
+       IMG_SIZE_T                      ui32Power2QueueSize = NearestPower2(ui32QueueSize);
+       SYS_DATA                        *psSysData;
+       PVRSRV_ERROR            eError;
+       IMG_HANDLE                      hMemBlock;
+
+       SysAcquireData(&psSysData);
+
+       
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_QUEUE_INFO),
+                                        (IMG_VOID **)&psQueueInfo, &hMemBlock,
+                                        "Queue Info");
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue struct"));
+               goto ErrorExit;
+       }
+       OSMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
+
+       psQueueInfo->hMemBlock[0] = hMemBlock;
+       psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+       
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                        ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
+                                        &psQueueInfo->pvLinQueueKM, &hMemBlock,
+                                        "Command Queue");
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer"));
+               goto ErrorExit;
+       }
+
+       psQueueInfo->hMemBlock[1] = hMemBlock;
+       psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
+
+       
+       PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
+       PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
+
+       psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
+
+       
+       if (psSysData->psQueueList == IMG_NULL)
+       {
+               eError = OSCreateResource(&psSysData->sQProcessResource);
+               if (eError != PVRSRV_OK)
+               {
+                       goto ErrorExit;
+               }
+       }
+
+       
+       eError = OSLockResource(&psSysData->sQProcessResource,
+                                                       KERNEL_ID);
+       if (eError != PVRSRV_OK)
+       {
+               goto ErrorExit;
+       }
+
+       psQueueInfo->psNextKM = psSysData->psQueueList;
+       psSysData->psQueueList = psQueueInfo;
+
+       eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+       if (eError != PVRSRV_OK)
+       {
+               goto ErrorExit;
+       }
+
+       *ppsQueueInfo = psQueueInfo;
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       if(psQueueInfo)
+       {
+               if(psQueueInfo->pvLinQueueKM)
+               {
+                       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                               psQueueInfo->ui32QueueSize,
+                                               psQueueInfo->pvLinQueueKM,
+                                               psQueueInfo->hMemBlock[1]);
+                       psQueueInfo->pvLinQueueKM = IMG_NULL;
+               }
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                       sizeof(PVRSRV_QUEUE_INFO),
+                                       psQueueInfo,
+                                       psQueueInfo->hMemBlock[0]);
+               
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
+{
+       PVRSRV_QUEUE_INFO       *psQueue;
+       SYS_DATA                        *psSysData;
+       PVRSRV_ERROR            eError;
+       IMG_BOOL                        bTimeout = IMG_TRUE;
+
+       SysAcquireData(&psSysData);
+
+       psQueue = psSysData->psQueueList;
+
+        
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+               {
+                       bTimeout = IMG_FALSE;
+                       break;
+               }
+               OSSleepms(1);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (bTimeout)
+       {
+               
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
+               eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
+               goto ErrorExit;
+       }
+
+       
+       eError = OSLockResource(&psSysData->sQProcessResource,
+                                                               KERNEL_ID);
+       if (eError != PVRSRV_OK)
+       {
+               goto ErrorExit;
+       }
+
+       if(psQueue == psQueueInfo)
+       {
+               psSysData->psQueueList = psQueueInfo->psNextKM;
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                       NearestPower2(psQueueInfo->ui32QueueSize) + PVRSRV_MAX_CMD_SIZE,
+                                       psQueueInfo->pvLinQueueKM,
+                                       psQueueInfo->hMemBlock[1]);
+               psQueueInfo->pvLinQueueKM = IMG_NULL;
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                       sizeof(PVRSRV_QUEUE_INFO),
+                                       psQueueInfo,
+                                       psQueueInfo->hMemBlock[0]);
+                
+               psQueueInfo = IMG_NULL; 
+       }
+       else
+       {
+               while(psQueue)
+               {
+                       if(psQueue->psNextKM == psQueueInfo)
+                       {
+                               psQueue->psNextKM = psQueueInfo->psNextKM;
+
+                               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                                       psQueueInfo->ui32QueueSize,
+                                                       psQueueInfo->pvLinQueueKM,
+                                                       psQueueInfo->hMemBlock[1]);
+                               psQueueInfo->pvLinQueueKM = IMG_NULL;
+                               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                                       sizeof(PVRSRV_QUEUE_INFO),
+                                                       psQueueInfo,
+                                                       psQueueInfo->hMemBlock[0]);
+                                
+                               psQueueInfo = IMG_NULL; 
+                               break;
+                       }
+                       psQueue = psQueue->psNextKM;
+               }
+
+               if(!psQueue)
+               {
+                       eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+                       if (eError != PVRSRV_OK)
+                       {
+                               goto ErrorExit;
+                       }
+                       eError = PVRSRV_ERROR_INVALID_PARAMS;
+                       goto ErrorExit;
+               }
+       }
+
+       
+       eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+       if (eError != PVRSRV_OK)
+       {
+               goto ErrorExit;
+       }
+
+       
+       if (psSysData->psQueueList == IMG_NULL)
+       {
+               eError = OSDestroyResource(&psSysData->sQProcessResource);
+               if (eError != PVRSRV_OK)
+               {
+                       goto ErrorExit;
+               }
+       }
+
+ErrorExit:
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+                                                                                               IMG_SIZE_T ui32ParamSize,
+                                                                                               IMG_VOID **ppvSpace)
+{
+       IMG_BOOL bTimeout = IMG_TRUE;
+
+       
+       ui32ParamSize =  (ui32ParamSize+3) & 0xFFFFFFFC;
+
+       if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
+       {
+               PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE));
+               return PVRSRV_ERROR_CMD_TOO_BIG;
+       }
+
+        
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize)
+               {
+                       bTimeout = IMG_FALSE;
+                       break;
+               }
+               OSSleepms(1);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (bTimeout == IMG_TRUE)
+       {
+               *ppvSpace = IMG_NULL;
+
+               return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+       }
+       else
+       {
+               *ppvSpace = (IMG_VOID *)((IMG_UINTPTR_T)psQueue->pvLinQueueUM + psQueue->ui32WriteOffset);
+       }
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO      *psQueue,
+                                                                                               PVRSRV_COMMAND          **ppsCommand,
+                                                                                               IMG_UINT32                      ui32DevIndex,
+                                                                                               IMG_UINT16                      CommandType,
+                                                                                               IMG_UINT32                      ui32DstSyncCount,
+                                                                                               PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+                                                                                               IMG_UINT32                      ui32SrcSyncCount,
+                                                                                               PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+                                                                                               IMG_SIZE_T                      ui32DataByteSize )
+{
+       PVRSRV_ERROR    eError;
+       PVRSRV_COMMAND  *psCommand;
+       IMG_SIZE_T              ui32CommandSize;
+       IMG_UINT32              i;
+
+       
+       ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
+
+       
+       ui32CommandSize = sizeof(PVRSRV_COMMAND)
+                                       + ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+                                       + ui32DataByteSize;
+
+       
+       eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand);
+       if(eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       psCommand->ui32ProcessID        = OSGetCurrentProcessIDKM();
+
+       
+       psCommand->ui32CmdSize          = ui32CommandSize; 
+       psCommand->ui32DevIndex         = ui32DevIndex;
+       psCommand->CommandType          = CommandType;
+       psCommand->ui32DstSyncCount     = ui32DstSyncCount;
+       psCommand->ui32SrcSyncCount     = ui32SrcSyncCount;
+       
+       
+       psCommand->psDstSync            = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
+
+
+       psCommand->psSrcSync            = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psDstSync)
+                                                               + (ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+       psCommand->pvData                       = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
+                                                               + (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+       psCommand->ui32DataSize         = ui32DataByteSize;
+
+       
+       for (i=0; i<ui32DstSyncCount; i++)
+       {
+               psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
+               psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
+               psCommand->psDstSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+
+               PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+                               i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+                               psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+                               psCommand->psDstSync[i].ui32ReadOpsPending,
+                               psCommand->psDstSync[i].ui32WriteOpsPending));
+       }
+
+       
+       for (i=0; i<ui32SrcSyncCount; i++)
+       {
+               psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
+               psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
+               psCommand->psSrcSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+
+               PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+                               i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+                               psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+                               psCommand->psSrcSync[i].ui32ReadOpsPending,
+                               psCommand->psSrcSync[i].ui32WriteOpsPending));
+       }
+
+       
+       *ppsCommand = psCommand;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+                                                                                               PVRSRV_COMMAND *psCommand)
+{
+       
+       
+       
+       if (psCommand->ui32DstSyncCount > 0)
+       {
+               psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+                                                                       + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND));
+       }
+
+       if (psCommand->ui32SrcSyncCount > 0)
+       {
+               psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+                                                                       + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+                                                                       + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+       }
+
+       psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+                                                                       + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+                                                                       + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
+                                                                       + (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+       
+       UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize);
+
+       return PVRSRV_OK;
+}
+
+
+
+static
+PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA                     *psSysData,
+                                                                 PVRSRV_COMMAND        *psCommand,
+                                                                 IMG_BOOL                      bFlush)
+{
+       PVRSRV_SYNC_OBJECT              *psWalkerObj;
+       PVRSRV_SYNC_OBJECT              *psEndObj;
+       IMG_UINT32                              i;
+       COMMAND_COMPLETE_DATA   *psCmdCompleteData;
+       PVRSRV_ERROR                    eError = PVRSRV_OK;
+       IMG_UINT32                              ui32WriteOpsComplete;
+       IMG_UINT32                              ui32ReadOpsComplete;
+       DEVICE_COMMAND_DATA             *psDeviceCommandData;
+       IMG_UINT32                              ui32CCBOffset;
+
+       
+       psWalkerObj = psCommand->psDstSync;
+       psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
+       while (psWalkerObj < psEndObj)
+       {
+               PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+               ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+               ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+               
+               if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+               ||      (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+               {
+                       if (!bFlush ||
+                               !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+                               !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+                       {
+                               return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+                       }
+               }
+
+               psWalkerObj++;
+       }
+
+       
+       psWalkerObj = psCommand->psSrcSync;
+       psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
+       while (psWalkerObj < psEndObj)
+       {
+               PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+               ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+               ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+               
+               if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+               || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+               {
+                       if (!bFlush &&
+                               SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
+                               SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+                       {
+                               PVR_DPF((PVR_DBG_WARNING,
+                                               "PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+                                               (IMG_UINTPTR_T)psSyncData, ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending));
+                       }
+
+                       if (!bFlush ||
+                               !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+                               !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+                       {
+                               return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+                       }
+               }
+               psWalkerObj++;
+       }
+
+       
+       if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                       "PVRSRVProcessCommand: invalid DeviceType 0x%x",
+                                       psCommand->ui32DevIndex));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
+       ui32CCBOffset = psDeviceCommandData[psCommand->CommandType].ui32CCBOffset;
+       psCmdCompleteData = psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[ui32CCBOffset];
+       if (psCmdCompleteData->bInUse)
+       {
+               
+               return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+       }
+
+       
+       psCmdCompleteData->bInUse = IMG_TRUE;
+
+       
+       psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
+       for (i=0; i<psCommand->ui32DstSyncCount; i++)
+       {
+               psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
+
+               PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
+                               i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+                               psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+                               psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+                               psCmdCompleteData->psDstSync[i].ui32WriteOpsPending,
+                               ui32CCBOffset));
+       }
+
+
+       
+       psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+       for (i=0; i<psCommand->ui32SrcSyncCount; i++)
+       {
+               psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+
+               PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
+                               i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+                               psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+                               psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+                               psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending,
+                               ui32CCBOffset));
+       }
+
+       
+
+
+
+
+
+
+
+
+
+       if (psDeviceCommandData[psCommand->CommandType].pfnCmdProc((IMG_HANDLE)psCmdCompleteData,
+                                                                                                                                                               psCommand->ui32DataSize,
+                                                                                                                                                               psCommand->pvData) == IMG_FALSE)
+       {
+               
+
+
+               psCmdCompleteData->bInUse = IMG_FALSE;
+               eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+       }
+
+
+       psDeviceCommandData[psCommand->CommandType].ui32CCBOffset = (ui32CCBOffset + 1) % DC_NUM_COMMANDS_PER_TYPE;
+
+       return eError;
+}
+
+
+static IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       if (psDeviceNode->bReProcessDeviceCommandComplete &&
+               psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+       {
+               (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+       }
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVProcessQueues(IMG_UINT32    ui32CallerID,
+                                                                IMG_BOOL       bFlush)
+{
+       PVRSRV_QUEUE_INFO       *psQueue;
+       SYS_DATA                        *psSysData;
+       PVRSRV_COMMAND          *psCommand;
+       PVRSRV_ERROR            eError;
+
+       SysAcquireData(&psSysData);
+
+       
+       psSysData->bReProcessQueues = IMG_FALSE;
+
+       
+       eError = OSLockResource(&psSysData->sQProcessResource,
+                                                       ui32CallerID);
+       if(eError != PVRSRV_OK)
+       {
+               
+               psSysData->bReProcessQueues = IMG_TRUE;
+
+               
+               if(ui32CallerID == ISR_ID)
+               {
+                       if (bFlush)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"PVRSRVProcessQueues: Couldn't acquire queue processing lock for FLUSH"));
+                       }
+                       else
+                       {
+                               PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Couldn't acquire queue processing lock"));
+                       }
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Queue processing lock-acquire failed when called from the Services driver."));
+                       PVR_DPF((PVR_DBG_MESSAGE,"                     This is due to MISR queue processing being interrupted by the Services driver."));
+               }
+
+               return PVRSRV_OK;
+       }
+
+       psQueue = psSysData->psQueueList;
+
+       if(!psQueue)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands"));
+       }
+
+       if (bFlush)
+       {
+               PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
+       }
+
+       while (psQueue)
+       {
+               while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset)
+               {
+                       psCommand = (PVRSRV_COMMAND*)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + psQueue->ui32ReadOffset);
+
+                       if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
+                       {
+                               
+                               UPDATE_QUEUE_ROFF(psQueue, psCommand->ui32CmdSize)
+
+                                       continue;
+                       }
+
+                       break;
+               }
+               psQueue = psQueue->psNextKM;
+       }
+
+       if (bFlush)
+       {
+               PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+       }
+
+       
+       List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+                                                                       &PVRSRVProcessQueues_ForEachCb);
+
+
+       
+       OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID);
+
+       
+       if(psSysData->bReProcessQueues)
+       {
+               return PVRSRV_ERROR_PROCESSING_BLOCKED;
+       }
+
+       return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_INTERNAL
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE  hCmdCookie,
+                                                                                  IMG_BOOL             bScheduleMISR)
+{
+       COMMAND_COMPLETE_DATA   *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+       SYS_DATA                                *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       
+       psCmdCompleteData->bInUse = IMG_FALSE;
+
+       
+       PVRSRVScheduleDeviceCallbacks();
+
+       if(bScheduleMISR)
+       {
+               OSScheduleMISR(psSysData);
+       }
+}
+
+#endif 
+
+
+IMG_EXPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE    hCmdCookie,
+                                                                IMG_BOOL       bScheduleMISR)
+{
+       IMG_UINT32                              i;
+       COMMAND_COMPLETE_DATA   *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+       SYS_DATA                                *psSysData;
+
+       SysAcquireData(&psSysData);
+
+       
+       for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
+       {
+               psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
+
+               PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+                               i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+                               psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+                               psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+                               psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+       }
+
+       
+       for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
+       {
+               psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete++;
+
+               PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+                               i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+                               psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+                               psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+                               psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+       }
+
+       pvr_trcmd_check_syn_completions(PVR_TRCMD_FLPCOMP);
+       
+       psCmdCompleteData->bInUse = IMG_FALSE;
+
+       
+       PVRSRVScheduleDeviceCallbacks();
+
+       if(bScheduleMISR)
+       {
+               OSScheduleMISR(psSysData);
+       }
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32            ui32DevIndex,
+                                                                                PFN_CMD_PROC   *ppfnCmdProcList,
+                                                                                IMG_UINT32             ui32MaxSyncsPerCmd[][2],
+                                                                                IMG_UINT32             ui32CmdCount)
+{
+       SYS_DATA                                *psSysData;
+       PVRSRV_ERROR                    eError;
+       IMG_UINT32                              ui32CmdCounter, ui32CmdTypeCounter;
+       IMG_SIZE_T                              ui32AllocSize;
+       DEVICE_COMMAND_DATA             *psDeviceCommandData;
+       COMMAND_COMPLETE_DATA   *psCmdCompleteData;
+
+       
+       if(ui32DevIndex >= SYS_DEVICE_COUNT)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                       "PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
+                                       ui32DevIndex));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       SysAcquireData(&psSysData);
+
+       
+       ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
+       eError = OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                        ui32AllocSize,
+                                               (IMG_VOID **)&psDeviceCommandData, IMG_NULL,
+                                        "Array of Pointers for Command Store");
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
+               goto ErrorExit;
+       }
+
+       psSysData->apsDeviceCommandData[ui32DevIndex] = psDeviceCommandData;
+
+       for (ui32CmdTypeCounter = 0; ui32CmdTypeCounter < ui32CmdCount; ui32CmdTypeCounter++)
+       {
+               psDeviceCommandData[ui32CmdTypeCounter].pfnCmdProc = ppfnCmdProcList[ui32CmdTypeCounter];
+               psDeviceCommandData[ui32CmdTypeCounter].ui32CCBOffset = 0;
+
+               for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+               {
+               
+
+               ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA) 
+                                                 + ((ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]
+                                                 +     ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1])
+                                         * sizeof(PVRSRV_SYNC_OBJECT));         
+
+               eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                                       ui32AllocSize,
+                                                               (IMG_VOID **)&psCmdCompleteData,
+                                                       IMG_NULL,
+                                                       "Command Complete Data");
+               if (eError != PVRSRV_OK)
+               {
+                               PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d", ui32CmdTypeCounter));
+                       goto ErrorExit;
+               }
+
+                       psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = psCmdCompleteData;
+               
+
+                       OSMemSet(psCmdCompleteData, 0x00, ui32AllocSize);
+
+               
+               psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
+                                                                               (((IMG_UINTPTR_T)psCmdCompleteData)
+                                                                               + sizeof(COMMAND_COMPLETE_DATA));
+               psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT*)
+                                                                               (((IMG_UINTPTR_T)psCmdCompleteData->psDstSync)
+                                                                                       + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]));
+
+               psCmdCompleteData->ui32AllocSize = ui32AllocSize;
+               }
+       }
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       
+
+       if (PVRSRVRemoveCmdProcListKM(ui32DevIndex, ui32CmdCount) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "PVRSRVRegisterCmdProcListKM: Failed to clean up after error, device 0x%x",
+                               ui32DevIndex));
+       }
+
+       return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+                                                                          IMG_UINT32 ui32CmdCount)
+{
+       SYS_DATA                *psSysData;
+       IMG_UINT32                              ui32CmdTypeCounter, ui32CmdCounter;
+       DEVICE_COMMAND_DATA             *psDeviceCommandData;
+       COMMAND_COMPLETE_DATA   *psCmdCompleteData;
+       IMG_SIZE_T                              ui32AllocSize;
+
+       
+       if(ui32DevIndex >= SYS_DEVICE_COUNT)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                       "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+                                       ui32DevIndex));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       SysAcquireData(&psSysData);
+
+       psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
+       if(psDeviceCommandData != IMG_NULL)
+       {
+               for (ui32CmdTypeCounter = 0; ui32CmdTypeCounter < ui32CmdCount; ui32CmdTypeCounter++)
+               {
+                       for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+                       {
+                               psCmdCompleteData = psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter];
+
+
+                               if (psCmdCompleteData != IMG_NULL)
+                               {
+                                       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, psCmdCompleteData->ui32AllocSize,
+                                                         psCmdCompleteData, IMG_NULL);
+                                       psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = IMG_NULL;
+                               }
+                       }
+               }
+
+               
+               ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psDeviceCommandData, IMG_NULL);
+               psSysData->apsDeviceCommandData[ui32DevIndex] = IMG_NULL;
+       }
+
+       return PVRSRV_OK;
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/ra.c b/drivers/staging/mrst/pvr/services4/srvkm/common/ra.c
new file mode 100644 (file)
index 0000000..49727cb
--- /dev/null
@@ -0,0 +1,1727 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "hash.h"
+#include "ra.h"
+#include "buffer_manager.h"
+#include "osfunc.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>
+#include "proc.h"
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+#include <stdio.h>
+#endif
+
+#define MINIMUM_HASH_SIZE (64)
+
+#if defined(VALIDATE_ARENA_TEST)
+
+typedef enum RESOURCE_DESCRIPTOR_TAG {
+
+       RESOURCE_SPAN_LIVE                              = 10,
+       RESOURCE_SPAN_FREE,
+       IMPORTED_RESOURCE_SPAN_START,
+       IMPORTED_RESOURCE_SPAN_LIVE,
+       IMPORTED_RESOURCE_SPAN_FREE,
+       IMPORTED_RESOURCE_SPAN_END,
+
+} RESOURCE_DESCRIPTOR;
+
+typedef enum RESOURCE_TYPE_TAG {
+
+       IMPORTED_RESOURCE_TYPE          = 20,
+       NON_IMPORTED_RESOURCE_TYPE
+
+} RESOURCE_TYPE;
+
+
+static IMG_UINT32 ui32BoundaryTagID = 0;
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena);
+#endif
+
+struct _BT_
+{
+       enum bt_type
+       {
+               btt_span,                               
+               btt_free,                               
+               btt_live                                
+       } type;
+
+       
+       IMG_UINTPTR_T base;
+       IMG_SIZE_T uSize;
+
+       
+       struct _BT_ *pNextSegment;
+       struct _BT_ *pPrevSegment;
+       
+       struct _BT_ *pNextFree;
+       struct _BT_ *pPrevFree;
+       
+       BM_MAPPING *psMapping;
+
+#if defined(VALIDATE_ARENA_TEST)
+       RESOURCE_DESCRIPTOR eResourceSpan;
+       RESOURCE_TYPE           eResourceType;
+
+       
+       IMG_UINT32                      ui32BoundaryTagID;
+#endif
+
+};
+typedef struct _BT_ BT;
+
+
+struct _RA_ARENA_
+{
+       
+       IMG_CHAR *name;
+
+       
+       IMG_SIZE_T uQuantum;
+
+       
+       IMG_BOOL (*pImportAlloc)(IMG_VOID *,
+                                                        IMG_SIZE_T uSize,
+                                                        IMG_SIZE_T *pActualSize,
+                                                        BM_MAPPING **ppsMapping,
+                                                        IMG_UINT32 uFlags,
+                                                        IMG_UINTPTR_T *pBase);
+       IMG_VOID (*pImportFree) (IMG_VOID *,
+                                                IMG_UINTPTR_T,
+                                                BM_MAPPING *psMapping);
+       IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
+
+       
+       IMG_VOID *pImportHandle;
+
+       
+#define FREE_TABLE_LIMIT 32
+
+       
+       BT *aHeadFree [FREE_TABLE_LIMIT];
+
+       
+       BT *pHeadSegment;
+       BT *pTailSegment;
+
+       
+       HASH_TABLE *pSegmentHash;
+
+#ifdef RA_STATS
+       RA_STATISTICS sStatistics;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+#define PROC_NAME_SIZE         32
+
+       struct proc_dir_entry* pProcInfo;
+       struct proc_dir_entry* pProcSegs;
+
+       IMG_BOOL bInitProcEntry;
+#endif
+};
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID RA_Dump (RA_ARENA *pArena);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
+
+#endif 
+
+#ifdef USE_BM_FREESPACE_CHECK
+IMG_VOID CheckBMFreespace(IMG_VOID);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS)
+{
+       IMG_CHAR *pT;
+
+       for(pT = pS; *pT != 0; pT++)
+       {
+               if (*pT == ' ' || *pT == '\t')
+               {
+                       *pT = '_';
+               }
+       }
+
+       return pS;
+}
+#endif
+
+static IMG_BOOL
+_RequestAllocFail (IMG_VOID *_h,
+                                 IMG_SIZE_T _uSize,
+                                 IMG_SIZE_T *_pActualSize,
+                                 BM_MAPPING **_ppsMapping,
+                                 IMG_UINT32 _uFlags,
+                                 IMG_UINTPTR_T *_pBase)
+{
+       PVR_UNREFERENCED_PARAMETER (_h);
+       PVR_UNREFERENCED_PARAMETER (_uSize);
+       PVR_UNREFERENCED_PARAMETER (_pActualSize);
+       PVR_UNREFERENCED_PARAMETER (_ppsMapping);
+       PVR_UNREFERENCED_PARAMETER (_uFlags);
+       PVR_UNREFERENCED_PARAMETER (_pBase);
+
+       return IMG_FALSE;
+}
+
+static IMG_UINT32
+pvr_log2 (IMG_SIZE_T n)
+{
+       IMG_UINT32 l = 0;
+       n>>=1;
+       while (n>0)
+       {
+               n>>=1;
+               l++;
+       }
+       return l;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsertAfter (RA_ARENA *pArena,
+                                                BT *pInsertionPoint,
+                                                BT *pBT)
+{
+       PVR_ASSERT (pArena != IMG_NULL);
+       PVR_ASSERT (pInsertionPoint != IMG_NULL);
+
+       if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL))
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       pBT->pNextSegment = pInsertionPoint->pNextSegment;
+       pBT->pPrevSegment = pInsertionPoint;
+       if (pInsertionPoint->pNextSegment == IMG_NULL)
+               pArena->pTailSegment = pBT;
+       else
+               pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+       pInsertionPoint->pNextSegment = pBT;
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       
+       if (pArena->pHeadSegment == IMG_NULL)
+       {
+               pArena->pHeadSegment = pArena->pTailSegment = pBT;
+               pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
+       }
+       else
+       {
+               BT *pBTScan;
+
+               if (pBT->base < pArena->pHeadSegment->base)
+               {
+                       
+                       pBT->pNextSegment = pArena->pHeadSegment;
+                       pArena->pHeadSegment->pPrevSegment = pBT;
+                       pArena->pHeadSegment = pBT;
+                       pBT->pPrevSegment = IMG_NULL;
+               }
+               else
+               {
+
+                       
+
+
+                       pBTScan = pArena->pHeadSegment;
+
+                       while ((pBTScan->pNextSegment != IMG_NULL)  && (pBT->base >= pBTScan->pNextSegment->base))
+                       {
+                               pBTScan = pBTScan->pNextSegment;
+                       }
+
+                       eError = _SegmentListInsertAfter (pArena, pBTScan, pBT);
+                       if (eError != PVRSRV_OK)
+                       {
+                               return eError;
+                       }
+               }
+       }
+       return eError;
+}
+
+static IMG_VOID
+_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
+{
+       if (pBT->pPrevSegment == IMG_NULL)
+               pArena->pHeadSegment = pBT->pNextSegment;
+       else
+               pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
+
+       if (pBT->pNextSegment == IMG_NULL)
+               pArena->pTailSegment = pBT->pPrevSegment;
+       else
+               pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
+}
+
+static BT *
+_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
+{
+       BT *pNeighbour;
+
+       PVR_ASSERT (pArena != IMG_NULL);
+
+       if (pArena == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena"));
+               return IMG_NULL;
+       }
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                       sizeof(BT),
+                                       (IMG_VOID **)&pNeighbour, IMG_NULL,
+                                       "Boundary Tag") != PVRSRV_OK)
+       {
+               return IMG_NULL;
+       }
+
+       OSMemSet(pNeighbour, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+       pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+       pNeighbour->pPrevSegment = pBT;
+       pNeighbour->pNextSegment = pBT->pNextSegment;
+       if (pBT->pNextSegment == IMG_NULL)
+               pArena->pTailSegment = pNeighbour;
+       else
+               pBT->pNextSegment->pPrevSegment = pNeighbour;
+       pBT->pNextSegment = pNeighbour;
+
+       pNeighbour->type = btt_free;
+       pNeighbour->uSize = pBT->uSize - uSize;
+       pNeighbour->base = pBT->base + uSize;
+       pNeighbour->psMapping = pBT->psMapping;
+       pBT->uSize = uSize;
+
+#if defined(VALIDATE_ARENA_TEST)
+       if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+       {
+               pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE;
+               pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+       }
+       else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+       {
+               pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+               pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE;
+       }
+       else
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized"));
+               PVR_DBG_BREAK;
+       }
+#endif
+
+       return pNeighbour;
+}
+
+static IMG_VOID
+_FreeListInsert (RA_ARENA *pArena, BT *pBT)
+{
+       IMG_UINT32 uIndex;
+       uIndex = pvr_log2 (pBT->uSize);
+       pBT->type = btt_free;
+       pBT->pNextFree = pArena->aHeadFree [uIndex];
+       pBT->pPrevFree = IMG_NULL;
+       if (pArena->aHeadFree[uIndex] != IMG_NULL)
+               pArena->aHeadFree[uIndex]->pPrevFree = pBT;
+       pArena->aHeadFree [uIndex] = pBT;
+}
+
+static IMG_VOID
+_FreeListRemove (RA_ARENA *pArena, BT *pBT)
+{
+       IMG_UINT32 uIndex;
+       uIndex = pvr_log2 (pBT->uSize);
+       if (pBT->pNextFree != IMG_NULL)
+               pBT->pNextFree->pPrevFree = pBT->pPrevFree;
+       if (pBT->pPrevFree == IMG_NULL)
+               pArena->aHeadFree[uIndex] = pBT->pNextFree;
+       else
+               pBT->pPrevFree->pNextFree = pBT->pNextFree;
+}
+
+static BT *
+_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+       BT *pBT;
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                       sizeof(BT),
+                                       (IMG_VOID **)&pBT, IMG_NULL,
+                                       "Boundary Tag") != PVRSRV_OK)
+       {
+               return IMG_NULL;
+       }
+
+       OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+       pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+       pBT->type = btt_span;
+       pBT->base = base;
+       pBT->uSize = uSize;
+       pBT->psMapping = IMG_NULL;
+
+       return pBT;
+}
+
+static BT *
+_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+       BT *pBT;
+
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                       sizeof(BT),
+                                       (IMG_VOID **)&pBT, IMG_NULL,
+                                       "Boundary Tag") != PVRSRV_OK)
+       {
+               return IMG_NULL;
+       }
+
+       OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+       pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+       pBT->type = btt_free;
+       pBT->base = base;
+       pBT->uSize = uSize;
+
+       return pBT;
+}
+
+static BT *
+_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+       BT *pBT;
+       PVR_ASSERT (pArena!=IMG_NULL);
+       if (pArena == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena"));
+               return IMG_NULL;
+       }
+
+       pBT = _BuildBT (base, uSize);
+       if (pBT != IMG_NULL)
+       {
+
+#if defined(VALIDATE_ARENA_TEST)
+               pBT->eResourceSpan = RESOURCE_SPAN_FREE;
+               pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+#endif
+
+               if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK)
+               {
+                       PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed"));
+                       return IMG_NULL;
+               }
+               _FreeListInsert (pArena, pBT);
+#ifdef RA_STATS
+               pArena->sStatistics.uTotalResourceCount+=uSize;
+               pArena->sStatistics.uFreeResourceCount+=uSize;
+               pArena->sStatistics.uSpanCount++;
+#endif
+       }
+       return pBT;
+}
+
+static BT *
+_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+       PVRSRV_ERROR eError;
+       BT *pSpanStart;
+       BT *pSpanEnd;
+       BT *pBT;
+
+       PVR_ASSERT (pArena != IMG_NULL);
+       if (pArena == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena"));
+               return IMG_NULL;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
+                         pArena->name, base, uSize));
+
+       pSpanStart = _BuildSpanMarker (base, uSize);
+       if (pSpanStart == IMG_NULL)
+       {
+               goto fail_start;
+       }
+
+#if defined(VALIDATE_ARENA_TEST)
+       pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START;
+       pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+       pSpanEnd = _BuildSpanMarker (base + uSize, 0);
+       if (pSpanEnd == IMG_NULL)
+       {
+               goto fail_end;
+       }
+
+#if defined(VALIDATE_ARENA_TEST)
+       pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END;
+       pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+       pBT = _BuildBT (base, uSize);
+       if (pBT == IMG_NULL)
+       {
+               goto fail_bt;
+       }
+
+#if defined(VALIDATE_ARENA_TEST)
+       pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+       pBT->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+       eError = _SegmentListInsert (pArena, pSpanStart);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_SegListInsert;
+       }
+
+       eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_SegListInsert;
+       }
+
+       _FreeListInsert (pArena, pBT);
+
+       eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_SegListInsert;
+       }
+
+#ifdef RA_STATS
+       pArena->sStatistics.uTotalResourceCount+=uSize;
+#endif
+       return pBT;
+
+  fail_SegListInsert:
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+       
+  fail_bt:
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
+       
+  fail_end:
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
+       
+  fail_start:
+       return IMG_NULL;
+}
+
+static IMG_VOID
+_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
+{
+       BT *pNeighbour;
+       IMG_UINTPTR_T uOrigBase;
+       IMG_SIZE_T uOrigSize;
+
+       PVR_ASSERT (pArena!=IMG_NULL);
+       PVR_ASSERT (pBT!=IMG_NULL);
+
+       if ((pArena == IMG_NULL) || (pBT == IMG_NULL))
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"_FreeBT: invalid parameter"));
+               return;
+       }
+
+#ifdef RA_STATS
+       pArena->sStatistics.uLiveSegmentCount--;
+       pArena->sStatistics.uFreeSegmentCount++;
+       pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+#endif
+
+       uOrigBase = pBT->base;
+       uOrigSize = pBT->uSize;
+
+       
+       pNeighbour = pBT->pPrevSegment;
+       if (pNeighbour!=IMG_NULL
+               && pNeighbour->type == btt_free
+               && pNeighbour->base + pNeighbour->uSize == pBT->base)
+       {
+               _FreeListRemove (pArena, pNeighbour);
+               _SegmentListRemove (pArena, pNeighbour);
+               pBT->base = pNeighbour->base;
+               pBT->uSize += pNeighbour->uSize;
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+               
+#ifdef RA_STATS
+               pArena->sStatistics.uFreeSegmentCount--;
+#endif
+       }
+
+       
+       pNeighbour = pBT->pNextSegment;
+       if (pNeighbour!=IMG_NULL
+               && pNeighbour->type == btt_free
+               && pBT->base + pBT->uSize == pNeighbour->base)
+       {
+               _FreeListRemove (pArena, pNeighbour);
+               _SegmentListRemove (pArena, pNeighbour);
+               pBT->uSize += pNeighbour->uSize;
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+               
+#ifdef RA_STATS
+               pArena->sStatistics.uFreeSegmentCount--;
+#endif
+       }
+
+       
+       if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
+       {
+               IMG_UINTPTR_T   uRoundedStart, uRoundedEnd;
+
+               
+               uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
+               
+               if (uRoundedStart < pBT->base)
+               {
+                       uRoundedStart += pArena->uQuantum;
+               }
+
+               
+               uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
+               
+               if (uRoundedEnd > (pBT->base + pBT->uSize))
+               {
+                       uRoundedEnd -= pArena->uQuantum;
+               }
+
+               if (uRoundedStart < uRoundedEnd)
+               {
+                       pArena->pBackingStoreFree(pArena->pImportHandle, (IMG_SIZE_T)uRoundedStart, (IMG_SIZE_T)uRoundedEnd, (IMG_HANDLE)0);
+               }
+       }
+
+       if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span
+               && pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span)
+       {
+               BT *next = pBT->pNextSegment;
+               BT *prev = pBT->pPrevSegment;
+               _SegmentListRemove (pArena, next);
+               _SegmentListRemove (pArena, prev);
+               _SegmentListRemove (pArena, pBT);
+               pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->psMapping);
+#ifdef RA_STATS
+               pArena->sStatistics.uSpanCount--;
+               pArena->sStatistics.uExportCount++;
+               pArena->sStatistics.uFreeSegmentCount--;
+               pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+               pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
+#endif
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
+               
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
+               
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+               
+       }
+       else
+               _FreeListInsert (pArena, pBT);
+}
+
+
+static IMG_BOOL
+_AttemptAllocAligned (RA_ARENA *pArena,
+                                         IMG_SIZE_T uSize,
+                                         BM_MAPPING **ppsMapping,
+                                         IMG_UINT32 uFlags,
+                                         IMG_UINT32 uAlignment,
+                                         IMG_UINT32 uAlignmentOffset,
+                                         IMG_UINTPTR_T *base)
+{
+       IMG_UINT32 uIndex;
+       PVR_ASSERT (pArena!=IMG_NULL);
+       if (pArena == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena"));
+               return IMG_FALSE;
+       }
+
+       if (uAlignment>1)
+               uAlignmentOffset %= uAlignment;
+
+       
+
+       uIndex = pvr_log2 (uSize);
+
+#if 0
+       
+       if (1u<<uIndex < uSize)
+               uIndex++;
+#endif
+
+       while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
+               uIndex++;
+
+       while (uIndex < FREE_TABLE_LIMIT)
+       {
+               if (pArena->aHeadFree[uIndex]!=IMG_NULL)
+               {
+                       
+                       BT *pBT;
+
+                       pBT = pArena->aHeadFree [uIndex];
+                       while (pBT!=IMG_NULL)
+                       {
+                               IMG_UINTPTR_T aligned_base;
+
+                               if (uAlignment>1)
+                                       aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset;
+                               else
+                                       aligned_base = pBT->base;
+                               PVR_DPF ((PVR_DBG_MESSAGE,
+                                                 "RA_AttemptAllocAligned: pBT-base=0x%x "
+                                                 "pBT-size=0x%x alignedbase=0x%x size=0x%x",
+                                               pBT->base, pBT->uSize, aligned_base, uSize));
+
+                               if (pBT->base + pBT->uSize >= aligned_base + uSize)
+                               {
+                                       if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags)
+                                       {
+                                               _FreeListRemove (pArena, pBT);
+
+                                               PVR_ASSERT (pBT->type == btt_free);
+
+#ifdef RA_STATS
+                                               pArena->sStatistics.uLiveSegmentCount++;
+                                               pArena->sStatistics.uFreeSegmentCount--;
+                                               pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+#endif
+
+                                               
+                                               if (aligned_base > pBT->base)
+                                               {
+                                                       BT *pNeighbour;
+                                                       pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base));
+                                                       
+                                                       if (pNeighbour==IMG_NULL)
+                                                       {
+                                                               PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
+                                                               
+                                                               _FreeListInsert (pArena, pBT);
+                                                               return IMG_FALSE;
+                                                       }
+
+                                                       _FreeListInsert (pArena, pBT);
+       #ifdef RA_STATS
+                                                       pArena->sStatistics.uFreeSegmentCount++;
+                                                       pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+       #endif
+                                                       pBT = pNeighbour;
+                                               }
+
+                                               
+                                               if (pBT->uSize > uSize)
+                                               {
+                                                       BT *pNeighbour;
+                                                       pNeighbour = _SegmentSplit (pArena, pBT, uSize);
+                                                       
+                                                       if (pNeighbour==IMG_NULL)
+                                                       {
+                                                               PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
+                                                               
+                                                               _FreeListInsert (pArena, pBT);
+                                                               return IMG_FALSE;
+                                                       }
+
+                                                       _FreeListInsert (pArena, pNeighbour);
+       #ifdef RA_STATS
+                                                       pArena->sStatistics.uFreeSegmentCount++;
+                                                       pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize;
+       #endif
+                                               }
+
+                                               pBT->type = btt_live;
+
+#if defined(VALIDATE_ARENA_TEST)
+                                               if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE)
+                                               {
+                                                       pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE;
+                                               }
+                                               else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+                                               {
+                                                       pBT->eResourceSpan = RESOURCE_SPAN_LIVE;
+                                               }
+                                               else
+                                               {
+                                                       PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized"));
+                                                       PVR_DBG_BREAK;
+                                               }
+#endif
+                                               if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT))
+                                               {
+                                                       _FreeBT (pArena, pBT, IMG_FALSE);
+                                                       return IMG_FALSE;
+                                               }
+
+                                               if (ppsMapping!=IMG_NULL)
+                                                       *ppsMapping = pBT->psMapping;
+
+                                               *base = pBT->base;
+
+                                               return IMG_TRUE;
+                                       }
+                                       else
+                                       {
+                                               PVR_DPF ((PVR_DBG_MESSAGE,
+                                                               "AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags));
+
+                                       }
+                               }
+                               pBT = pBT->pNextFree;
+                       }
+
+               }
+               uIndex++;
+       }
+
+       return IMG_FALSE;
+}
+
+
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+                  IMG_UINTPTR_T base,
+                  IMG_SIZE_T uSize,
+                  BM_MAPPING *psMapping,
+                  IMG_SIZE_T uQuantum,
+                  IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
+                                    BM_MAPPING **ppsMapping, IMG_UINT32 _flags, IMG_UINTPTR_T *pBase),
+                  IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
+                  IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
+                  IMG_VOID *pImportHandle)
+{
+       RA_ARENA *pArena;
+       BT *pBT;
+       IMG_INT i;
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
+                         name, base, uSize, (IMG_UINTPTR_T)imp_alloc, (IMG_UINTPTR_T)imp_free));
+
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof (*pArena),
+                                        (IMG_VOID **)&pArena, IMG_NULL,
+                                        "Resource Arena") != PVRSRV_OK)
+       {
+               goto arena_fail;
+       }
+
+       pArena->name = name;
+       pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : &_RequestAllocFail;
+       pArena->pImportFree = imp_free;
+       pArena->pBackingStoreFree = backingstore_free;
+       pArena->pImportHandle = pImportHandle;
+       for (i=0; i<FREE_TABLE_LIMIT; i++)
+               pArena->aHeadFree[i] = IMG_NULL;
+       pArena->pHeadSegment = IMG_NULL;
+       pArena->pTailSegment = IMG_NULL;
+       pArena->uQuantum = uQuantum;
+
+#ifdef RA_STATS
+       pArena->sStatistics.uSpanCount = 0;
+       pArena->sStatistics.uLiveSegmentCount = 0;
+       pArena->sStatistics.uFreeSegmentCount = 0;
+       pArena->sStatistics.uFreeResourceCount = 0;
+       pArena->sStatistics.uTotalResourceCount = 0;
+       pArena->sStatistics.uCumulativeAllocs = 0;
+       pArena->sStatistics.uCumulativeFrees = 0;
+       pArena->sStatistics.uImportCount = 0;
+       pArena->sStatistics.uExportCount = 0;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+       if(strcmp(pArena->name,"") != 0)
+       {
+               IMG_INT ret;
+               IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
+               IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
+               struct proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *,
+                                                                                IMG_VOID*,
+                                                                                pvr_next_proc_seq_t,
+                                                                                pvr_show_proc_seq_t,
+                                                                                pvr_off2element_proc_seq_t,
+                                                                                pvr_startstop_proc_seq_t,
+                                                                                write_proc_t);
+
+               pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+               
+               pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
+
+               ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
+               if (ret > 0 && ret < sizeof(szProcInfoName))
+               {
+                       pArena->pProcInfo =  pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL,
+                                                                                        RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL);
+               }
+               else
+               {
+                       pArena->pProcInfo = 0;
+                       PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
+               }
+
+               ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name);
+               if (ret > 0 && ret < sizeof(szProcInfoName))
+               {
+                       pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL,
+                                                                                        RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL);
+               }
+               else
+               {
+                       pArena->pProcSegs = 0;
+                       PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
+               }
+       }
+#endif 
+
+       pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
+       if (pArena->pSegmentHash==IMG_NULL)
+       {
+               goto hash_fail;
+       }
+       if (uSize>0)
+       {
+               uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
+               pBT = _InsertResource (pArena, base, uSize);
+               if (pBT == IMG_NULL)
+               {
+                       goto insert_fail;
+               }
+               pBT->psMapping = psMapping;
+
+       }
+       return pArena;
+
+insert_fail:
+       HASH_Delete (pArena->pSegmentHash);
+hash_fail:
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+       
+arena_fail:
+       return IMG_NULL;
+}
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena)
+{
+       IMG_UINT32 uIndex;
+
+       PVR_ASSERT(pArena != IMG_NULL);
+
+       if (pArena == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena"));
+               return;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "RA_Delete: name='%s'", pArena->name));
+
+       for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
+               pArena->aHeadFree[uIndex] = IMG_NULL;
+
+       while (pArena->pHeadSegment != IMG_NULL)
+       {
+               BT *pBT = pArena->pHeadSegment;
+
+               if (pBT->type != btt_free)
+               {
+                       PVR_DPF ((PVR_DBG_ERROR,"Leaking base = 0x%x type=%d size=0x%x", pBT->base, pBT->type, pBT->uSize));
+                       RA_Free(pArena, pBT->base, IMG_FALSE);
+               }
+               else
+               {
+                       _SegmentListRemove (pArena, pBT);
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+#ifdef RA_STATS
+                       pArena->sStatistics.uSpanCount--;
+#endif
+               }
+       }
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+       {
+               IMG_VOID (*pfnRemoveProcEntrySeq)(struct proc_dir_entry*);
+
+               pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq;
+
+               if (pArena->pProcInfo != 0)
+               {
+                       pfnRemoveProcEntrySeq( pArena->pProcInfo );
+               }
+
+               if (pArena->pProcSegs != 0)
+               {
+                       pfnRemoveProcEntrySeq( pArena->pProcSegs );
+               }
+       }
+#endif
+       HASH_Delete (pArena->pSegmentHash);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+       
+}
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena)
+{
+       PVR_ASSERT(pArena != IMG_NULL);
+
+       if (pArena != IMG_NULL)
+       {
+               while (pArena->pHeadSegment != IMG_NULL)
+               {
+                       BT *pBT = pArena->pHeadSegment;
+                       if (pBT->type != btt_free)
+                       {
+                               PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!"));
+                               PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
+                               return IMG_FALSE;
+                       }
+               }
+       }
+
+       return IMG_TRUE;
+}
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+       PVR_ASSERT (pArena != IMG_NULL);
+
+       if (pArena == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena"));
+               return IMG_FALSE;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base, uSize));
+
+       uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum;
+       return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
+}
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+                 IMG_SIZE_T uRequestSize,
+                 IMG_SIZE_T *pActualSize,
+                 BM_MAPPING **ppsMapping,
+                 IMG_UINT32 uFlags,
+                 IMG_UINT32 uAlignment,
+                 IMG_UINT32 uAlignmentOffset,
+                 IMG_UINTPTR_T *base)
+{
+       IMG_BOOL bResult;
+       IMG_SIZE_T uSize = uRequestSize;
+
+       PVR_ASSERT (pArena!=IMG_NULL);
+
+       if (pArena == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena"));
+               return IMG_FALSE;
+       }
+
+#if defined(VALIDATE_ARENA_TEST)
+       ValidateArena(pArena);
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+       CheckBMFreespace();
+#endif
+
+       if (pActualSize != IMG_NULL)
+       {
+               *pActualSize = uSize;
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
+                  pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
+
+       
+
+       bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
+                                                                       uAlignment, uAlignmentOffset, base);
+       if (!bResult)
+       {
+               BM_MAPPING *psImportMapping;
+               IMG_UINTPTR_T import_base;
+               IMG_SIZE_T uImportSize = uSize;
+
+               
+
+
+               if (uAlignment > pArena->uQuantum)
+               {
+                       uImportSize += (uAlignment - 1);
+               }
+
+               
+               uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
+
+               bResult =
+                       pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
+                                                                &psImportMapping, uFlags, &import_base);
+               if (bResult)
+               {
+                       BT *pBT;
+                       pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
+                       
+                       if (pBT == IMG_NULL)
+                       {
+                               
+                               pArena->pImportFree(pArena->pImportHandle, import_base,
+                                                                       psImportMapping);
+                               PVR_DPF ((PVR_DBG_MESSAGE,
+                                                 "RA_Alloc: name='%s', size=0x%x failed!",
+                                                 pArena->name, uSize));
+                               
+                               return IMG_FALSE;
+                       }
+                       pBT->psMapping = psImportMapping;
+#ifdef RA_STATS
+                       pArena->sStatistics.uFreeSegmentCount++;
+                       pArena->sStatistics.uFreeResourceCount += uImportSize;
+                       pArena->sStatistics.uImportCount++;
+                       pArena->sStatistics.uSpanCount++;
+#endif
+                       bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
+                                                                                  uAlignment, uAlignmentOffset,
+                                                                                  base);
+                       if (!bResult)
+                       {
+                               PVR_DPF ((PVR_DBG_MESSAGE,
+                                                 "RA_Alloc: name='%s' uAlignment failed!",
+                                                 pArena->name));
+                       }
+               }
+       }
+#ifdef RA_STATS
+       if (bResult)
+               pArena->sStatistics.uCumulativeAllocs++;
+#endif
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
+                         pArena->name, uSize, *base, bResult));
+
+       
+
+#if defined(VALIDATE_ARENA_TEST)
+       ValidateArena(pArena);
+#endif
+
+       return bResult;
+}
+
+
+#if defined(VALIDATE_ARENA_TEST)
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena)
+{
+       BT* pSegment;
+       RESOURCE_DESCRIPTOR eNextSpan;
+
+       pSegment = pArena->pHeadSegment;
+
+       if (pSegment == IMG_NULL)
+       {
+               return 0;
+       }
+
+       if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+       {
+               PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START);
+
+               while (pSegment->pNextSegment)
+               {
+                       eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+                       switch (pSegment->eResourceSpan)
+                       {
+                               case IMPORTED_RESOURCE_SPAN_LIVE:
+
+                                       if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+                                                 (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+                                                 (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+                                       {
+                                               
+                                               PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+                                                               pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+                                               PVR_DBG_BREAK;
+                                       }
+                               break;
+
+                               case IMPORTED_RESOURCE_SPAN_FREE:
+
+                                       if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+                                                 (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+                                       {
+                                               
+                                               PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+                                                               pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+                                               PVR_DBG_BREAK;
+                                       }
+                               break;
+
+                               case IMPORTED_RESOURCE_SPAN_END:
+
+                                       if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+                                               (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+                                               (eNextSpan == IMPORTED_RESOURCE_SPAN_END))
+                                       {
+                                               
+                                               PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+                                                               pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+                                               PVR_DBG_BREAK;
+                                       }
+                               break;
+
+
+                               case IMPORTED_RESOURCE_SPAN_START:
+
+                                       if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+                                                 (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
+                                       {
+                                               
+                                               PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+                                                               pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+                                               PVR_DBG_BREAK;
+                                       }
+                               break;
+
+                               default:
+                                       PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+                                                               pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+                                       PVR_DBG_BREAK;
+                               break;
+                       }
+                       pSegment = pSegment->pNextSegment;
+               }
+       }
+       else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+       {
+               PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE));
+
+               while (pSegment->pNextSegment)
+               {
+                       eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+                       switch (pSegment->eResourceSpan)
+                       {
+                               case RESOURCE_SPAN_LIVE:
+
+                                       if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+                                                 (eNextSpan == RESOURCE_SPAN_LIVE)))
+                                       {
+                                               
+                                               PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+                                                               pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+                                               PVR_DBG_BREAK;
+                                       }
+                               break;
+
+                               case RESOURCE_SPAN_FREE:
+
+                                       if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+                                                 (eNextSpan == RESOURCE_SPAN_LIVE)))
+                                       {
+                                               
+                                               PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+                                                               pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+                                               PVR_DBG_BREAK;
+                                       }
+                               break;
+
+                               default:
+                                       PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+                                                               pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+                                       PVR_DBG_BREAK;
+                               break;
+                       }
+                       pSegment = pSegment->pNextSegment;
+               }
+
+       }
+       else
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized"));
+
+               PVR_DBG_BREAK;
+       }
+
+       return 0;
+}
+
+#endif
+
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
+{
+       BT *pBT;
+
+       PVR_ASSERT (pArena != IMG_NULL);
+
+       if (pArena == IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena"));
+               return;
+       }
+
+#ifdef USE_BM_FREESPACE_CHECK
+       CheckBMFreespace();
+#endif
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                         "RA_Free: name='%s', base=0x%x", pArena->name, base));
+
+       pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base);
+       PVR_ASSERT (pBT != IMG_NULL);
+
+       if (pBT)
+       {
+               PVR_ASSERT (pBT->base == base);
+
+#ifdef RA_STATS
+               pArena->sStatistics.uCumulativeFrees++;
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+{
+       IMG_BYTE* p;
+       IMG_BYTE* endp;
+
+       p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+       endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize));
+       while ((IMG_UINT32)p & 3)
+       {
+               *p++ = 0xAA;
+       }
+       while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc))
+       {
+               *(IMG_UINT32*)p = 0xAAAAAAAA;
+               p += sizeof(IMG_UINT32);
+       }
+       while (p < endp)
+       {
+               *p++ = 0xAA;
+       }
+       PVR_DPF((PVR_DBG_MESSAGE,"BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),endp-1,pBT->uSize));
+}
+#endif
+               _FreeBT (pArena, pBT, bFreeBackingStore);
+       }
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
+{
+       BT        *pBT;
+
+       if (psSegDetails->hSegment)
+       {
+               pBT = (BT *)psSegDetails->hSegment;
+       }
+       else
+       {
+               RA_ARENA *pArena = (RA_ARENA *)hArena;
+
+               pBT = pArena->pHeadSegment;
+       }
+       
+       while (pBT != IMG_NULL)
+       {
+               if (pBT->type == btt_live)
+               {
+                       psSegDetails->uiSize = pBT->uSize;
+                       psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
+                       psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment;
+
+                       return IMG_TRUE;
+               }
+
+               pBT = pBT->pNextSegment;
+       }
+
+       psSegDetails->uiSize = 0;
+       psSegDetails->sCpuPhyAddr.uiAddr = 0;
+       psSegDetails->hSegment = (IMG_HANDLE)IMG_UNDEF;
+
+       return IMG_FALSE;
+}
+
+
+#ifdef USE_BM_FREESPACE_CHECK
+RA_ARENA* pJFSavedArena = IMG_NULL;
+
+IMG_VOID CheckBMFreespace(IMG_VOID)
+{
+       BT *pBT;
+       IMG_BYTE* p;
+       IMG_BYTE* endp;
+
+       if (pJFSavedArena != IMG_NULL)
+       {
+               for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+               {
+                       if (pBT->type == btt_free)
+                       {
+                               p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+                               endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc);
+
+                               while ((IMG_UINT32)p & 3)
+                               {
+                                       if (*p++ != 0xAA)
+                                       {
+                                               fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+                                               for (;;);
+                                               break;
+                                       }
+                               }
+                               while (p < endp)
+                               {
+                                       if (*(IMG_UINT32*)p != 0xAAAAAAAA)
+                                       {
+                                               fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+                                               for (;;);
+                                               break;
+                                       }
+                                       p += 4;
+                               }
+                       }
+               }
+       }
+}
+#endif
+
+
+#if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS)
+static IMG_CHAR *
+_BTType (IMG_INT eType)
+{
+       switch (eType)
+       {
+       case btt_span: return "span";
+       case btt_free: return "free";
+       case btt_live: return "live";
+       }
+       return "junk";
+}
+#endif 
+
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID
+RA_Dump (RA_ARENA *pArena)
+{
+       BT *pBT;
+       PVR_ASSERT (pArena != IMG_NULL);
+       PVR_DPF ((PVR_DBG_MESSAGE,"Arena '%s':", pArena->name));
+       PVR_DPF ((PVR_DBG_MESSAGE,"  alloc=%08X free=%08X handle=%08X quantum=%d",
+                        pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle,
+                        pArena->uQuantum));
+       PVR_DPF ((PVR_DBG_MESSAGE,"  segment Chain:"));
+       if (pArena->pHeadSegment != IMG_NULL &&
+           pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+               PVR_DPF ((PVR_DBG_MESSAGE,"  error: head boundary tag has invalid pPrevSegment"));
+       if (pArena->pTailSegment != IMG_NULL &&
+           pArena->pTailSegment->pNextSegment != IMG_NULL)
+               PVR_DPF ((PVR_DBG_MESSAGE,"  error: tail boundary tag has invalid pNextSegment"));
+
+       for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+       {
+               PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s ref=%08X",
+                                (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type),
+                                pBT->pRef));
+       }
+
+#ifdef HASH_TRACE
+       HASH_Dump (pArena->pSegmentHash);
+#endif
+}
+#endif 
+
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+       RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+       IMG_INT off = (IMG_INT)el;
+
+       switch (off)
+       {
+       case 1:
+               seq_printf(sfile, "quantum\t\t\t%u\n", pArena->uQuantum);
+               break;
+       case 2:
+               seq_printf(sfile, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle);
+               break;
+#ifdef RA_STATS
+       case 3:
+               seq_printf(sfile,"span count\t\t%u\n", pArena->sStatistics.uSpanCount);
+               break;
+       case 4:
+               seq_printf(sfile, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount);
+               break;
+       case 5:
+               seq_printf(sfile, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount);
+               break;
+       case 6:
+               seq_printf(sfile, "free resource count\t%u (0x%x)\n",
+                                                       pArena->sStatistics.uFreeResourceCount,
+                                                       (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+               break;
+       case 7:
+               seq_printf(sfile, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs);
+               break;
+       case 8:
+               seq_printf(sfile, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees);
+               break;
+       case 9:
+               seq_printf(sfile, "import count\t\t%u\n", pArena->sStatistics.uImportCount);
+               break;
+       case 10:
+               seq_printf(sfile, "export count\t\t%u\n", pArena->sStatistics.uExportCount);
+               break;
+#endif
+       }
+
+}
+
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off)
+{
+#ifdef RA_STATS
+       if(off <= 9)
+#else
+       if(off <= 1)
+#endif
+               return (void*)(IMG_INT)(off+1);
+       return 0;
+}
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+       RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+       BT *pBT = (BT*)el;
+
+       if (el == PVR_PROC_SEQ_START_TOKEN)
+       {
+               seq_printf(sfile, "Arena \"%s\"\nBase         Size Type Ref\n", pArena->name);
+               return;
+       }
+
+       if (pBT)
+       {
+               seq_printf(sfile, "%08x %8x %4s %08x\n",
+                                  (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type),
+                              (IMG_UINT)pBT->psMapping);
+       }
+}
+
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+       RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+       BT *pBT = 0;
+
+       if(off == 0)
+               return PVR_PROC_SEQ_START_TOKEN;
+
+       for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment);
+
+       return (void*)pBT;
+}
+
+#endif 
+
+
+#ifdef RA_STATS
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+                                                       IMG_CHAR **ppszStr,
+                                                       IMG_UINT32 *pui32StrLen)
+{
+       IMG_CHAR        *pszStr = *ppszStr;
+       IMG_UINT32      ui32StrLen = *pui32StrLen;
+       IMG_INT32       i32Count;
+       BT                      *pBT;
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "  allocCB=%p freeCB=%p handle=%p quantum=%d\n",
+                                                        pArena->pImportAlloc,
+                                                        pArena->pImportFree,
+                                                        pArena->pImportHandle,
+                                                        pArena->uQuantum);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%u\n", pArena->sStatistics.uSpanCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%u (0x%x)\n",
+                                                       pArena->sStatistics.uFreeResourceCount,
+                                                       (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%u\n", pArena->sStatistics.uImportCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%u\n", pArena->sStatistics.uExportCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "  segment Chain:\n");
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       if (pArena->pHeadSegment != IMG_NULL &&
+           pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+       {
+               CHECK_SPACE(ui32StrLen);
+               i32Count = OSSNPrintf(pszStr, 100, "  error: head boundary tag has invalid pPrevSegment\n");
+               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+       }
+
+       if (pArena->pTailSegment != IMG_NULL &&
+           pArena->pTailSegment->pNextSegment != IMG_NULL)
+       {
+               CHECK_SPACE(ui32StrLen);
+               i32Count = OSSNPrintf(pszStr, 100, "  error: tail boundary tag has invalid pNextSegment\n");
+               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+       }
+
+       for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+       {
+               CHECK_SPACE(ui32StrLen);
+               i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%p\n",
+                                                                                        (IMG_UINT32) pBT->base,
+                                                                                        pBT->uSize,
+                                                                                        _BTType(pBT->type),
+                                                                                        pBT->psMapping);
+               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+       }
+
+       *ppszStr = pszStr;
+       *pui32StrLen = ui32StrLen;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
+                                                               IMG_CHAR **ppszStr, 
+                                                               IMG_UINT32 *pui32StrLen)
+{
+       IMG_CHAR        *pszStr = *ppszStr;
+       IMG_UINT32      ui32StrLen = *pui32StrLen;
+       IMG_INT32       i32Count;
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "Bytes free: Arena %-30s: %u (0x%x)\n", pArena->name,
+               pArena->sStatistics.uFreeResourceCount,
+               pArena->sStatistics.uFreeResourceCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+       *ppszStr = pszStr;
+       *pui32StrLen = ui32StrLen;
+       
+       return PVRSRV_OK;
+}
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/resman.c b/drivers/staging/mrst/pvr/services4/srvkm/common/resman.c
new file mode 100644 (file)
index 0000000..ed385ba
--- /dev/null
@@ -0,0 +1,806 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+
+#ifdef __linux__
+#include <linux/version.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
+#include <linux/hardirq.h>
+#else
+#include <asm/hardirq.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+static DEFINE_SEMAPHORE(lock);
+
+#define ACQUIRE_SYNC_OBJ  do {                                                 \
+               if (in_interrupt()) {                                                   \
+                       printk ("ISR cannot take RESMAN mutex\n");      \
+                       BUG();                                                                          \
+               }                                                                                               \
+               else down (&lock);                                                              \
+} while (0)
+#define RELEASE_SYNC_OBJ up (&lock)
+
+#else
+
+#define ACQUIRE_SYNC_OBJ
+#define RELEASE_SYNC_OBJ
+
+#endif
+
+#define RESMAN_SIGNATURE 0x12345678
+
+typedef struct _RESMAN_ITEM_
+{
+#ifdef DEBUG
+       IMG_UINT32                              ui32Signature;
+#endif
+       struct _RESMAN_ITEM_    **ppsThis;      
+       struct _RESMAN_ITEM_    *psNext;        
+
+       IMG_UINT32                              ui32Flags;      
+       IMG_UINT32                              ui32ResType;
+
+       IMG_PVOID                               pvParam;        
+       IMG_UINT32                              ui32Param;      
+
+       RESMAN_FREE_FN                  pfnFreeResource;
+} RESMAN_ITEM;
+
+
+typedef struct _RESMAN_CONTEXT_
+{
+#ifdef DEBUG
+       IMG_UINT32                                      ui32Signature;
+#endif
+       struct  _RESMAN_CONTEXT_        **ppsThis;
+       struct  _RESMAN_CONTEXT_        *psNext;
+
+       PVRSRV_PER_PROCESS_DATA         *psPerProc; 
+
+       RESMAN_ITEM                                     *psResItemList;
+
+} RESMAN_CONTEXT;
+
+
+typedef struct
+{
+       RESMAN_CONTEXT  *psContextList; 
+
+} RESMAN_LIST, *PRESMAN_LIST;  
+
+
+PRESMAN_LIST   gpsResList = IMG_NULL;
+
+#include "lists.h"      
+
+static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
+static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
+static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
+static IMPLEMENT_LIST_REVERSE(RESMAN_ITEM)
+
+static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
+
+
+#define PRINT_RESLIST(x, y, z)
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback);
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT     psContext,
+                                                                                  IMG_UINT32           ui32SearchCriteria,
+                                                                                  IMG_UINT32           ui32ResType,
+                                                                                  IMG_PVOID            pvParam,
+                                                                                  IMG_UINT32           ui32Param,
+                                                                                  IMG_BOOL                     bExecuteCallback);
+
+
+#ifdef DEBUG
+       static IMG_VOID ValidateResList(PRESMAN_LIST psResList);
+       #define VALIDATERESLIST() ValidateResList(gpsResList)
+#else
+       #define VALIDATERESLIST()
+#endif
+
+
+
+
+
+
+PVRSRV_ERROR ResManInit(IMG_VOID)
+{
+       if (gpsResList == IMG_NULL)
+       {
+               
+               if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof(*gpsResList),
+                                               (IMG_VOID **)&gpsResList, IMG_NULL,
+                                               "Resource Manager List") != PVRSRV_OK)
+               {
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+
+               
+               gpsResList->psContextList = IMG_NULL;
+
+               
+               VALIDATERESLIST();
+       }
+
+       return PVRSRV_OK;
+}
+
+
+IMG_VOID ResManDeInit(IMG_VOID)
+{
+       if (gpsResList != IMG_NULL)
+       {
+               
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
+               gpsResList = IMG_NULL;
+       }
+}
+
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE                    hPerProc,
+                                                                PRESMAN_CONTEXT        *phResManContext)
+{
+       PVRSRV_ERROR    eError;
+       PRESMAN_CONTEXT psResManContext;
+
+       
+       ACQUIRE_SYNC_OBJ;
+
+       
+       VALIDATERESLIST();
+
+       
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
+                                               (IMG_VOID **)&psResManContext, IMG_NULL,
+                                               "Resource Manager Context");
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
+
+               
+               VALIDATERESLIST();
+
+               
+               RELEASE_SYNC_OBJ;
+
+               return eError;
+       }
+
+#ifdef DEBUG
+       psResManContext->ui32Signature = RESMAN_SIGNATURE;
+#endif 
+       psResManContext->psResItemList  = IMG_NULL;
+       psResManContext->psPerProc = hPerProc;
+
+       
+       List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
+
+       
+       VALIDATERESLIST();
+
+       
+       RELEASE_SYNC_OBJ;
+
+       *phResManContext = psResManContext;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
+                                                               IMG_BOOL                bKernelContext)
+{
+       
+       ACQUIRE_SYNC_OBJ;
+
+       
+       VALIDATERESLIST();
+
+       
+       PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
+
+       
+
+       if (!bKernelContext)
+       {
+               
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
+
+               
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
+
+               
+               
+               List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
+               List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);  
+
+               
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
+
+               
+
+               
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+               
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+               
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SYNC_INFO, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
+               FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_MEM_INFO, 0, 0, IMG_TRUE);
+       }
+
+       
+       PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
+
+       
+       List_RESMAN_CONTEXT_Remove(psResManContext);
+
+       
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
+       
+
+
+       
+       VALIDATERESLIST();
+
+       
+       PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
+
+       
+       RELEASE_SYNC_OBJ;
+}
+
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
+                                                          IMG_UINT32           ui32ResType,
+                                                          IMG_PVOID            pvParam,
+                                                          IMG_UINT32           ui32Param,
+                                                          RESMAN_FREE_FN       pfnFreeResource)
+{
+       PRESMAN_ITEM    psNewResItem;
+
+       PVR_ASSERT(psResManContext != IMG_NULL);
+       PVR_ASSERT(ui32ResType != 0);
+
+       if (psResManContext == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
+               return (PRESMAN_ITEM) IMG_NULL;
+       }
+
+       
+       ACQUIRE_SYNC_OBJ;
+
+       
+       VALIDATERESLIST();
+
+       PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+                       "Context 0x%x, ResType 0x%x, pvParam 0x%x, ui32Param 0x%x, "
+                       "FreeFunc %08X",
+                       (IMG_UINTPTR_T)psResManContext,
+                       ui32ResType,
+                       (IMG_UINTPTR_T)pvParam,
+                       ui32Param,
+                       (IMG_UINTPTR_T)pfnFreeResource));
+
+       
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                  sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
+                                  IMG_NULL,
+                                  "Resource Manager Item") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
+                               "ERROR allocating new resource item"));
+
+               
+               RELEASE_SYNC_OBJ;
+
+               return((PRESMAN_ITEM)IMG_NULL);
+       }
+
+       
+#ifdef DEBUG
+       psNewResItem->ui32Signature             = RESMAN_SIGNATURE;
+#endif 
+       psNewResItem->ui32ResType               = ui32ResType;
+       psNewResItem->pvParam                   = pvParam;
+       psNewResItem->ui32Param                 = ui32Param;
+       psNewResItem->pfnFreeResource   = pfnFreeResource;
+       psNewResItem->ui32Flags             = 0;
+
+       
+       List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
+
+       
+       VALIDATERESLIST();
+
+       
+       RELEASE_SYNC_OBJ;
+
+       return(psNewResItem);
+}
+
+PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM    *psResItem)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psResItem != IMG_NULL);
+
+       if (psResItem == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
+               return PVRSRV_OK;
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X",
+                       (IMG_UINTPTR_T)psResItem));
+
+       
+       ACQUIRE_SYNC_OBJ;
+
+       
+       VALIDATERESLIST();
+
+       
+       eError = FreeResourceByPtr(psResItem, IMG_TRUE);
+
+       
+       VALIDATERESLIST();
+
+       
+       RELEASE_SYNC_OBJ;
+
+       return(eError);
+}
+
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT   psResManContext,
+                                                                        IMG_UINT32                     ui32SearchCriteria,
+                                                                        IMG_UINT32                     ui32ResType,
+                                                                        IMG_PVOID                      pvParam,
+                                                                        IMG_UINT32                     ui32Param)
+{
+       PVRSRV_ERROR    eError;
+
+       PVR_ASSERT(psResManContext != IMG_NULL);
+
+       
+       ACQUIRE_SYNC_OBJ;
+
+       
+       VALIDATERESLIST();
+
+       PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
+                       "Context 0x%x, Criteria 0x%x, Type 0x%x, Addr 0x%x, Param 0x%x",
+                       (IMG_UINTPTR_T)psResManContext, ui32SearchCriteria, ui32ResType,
+                       (IMG_UINTPTR_T)pvParam, ui32Param));
+
+       
+       eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+                                                                       ui32ResType, pvParam, ui32Param,
+                                                                       IMG_TRUE);
+
+       
+       VALIDATERESLIST();
+
+       
+       RELEASE_SYNC_OBJ;
+
+       return eError;
+}
+
+
+PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM           *psResItem,
+                                                        PRESMAN_CONTEXT        psNewResManContext)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       PVR_ASSERT(psResItem != IMG_NULL);
+
+       if (psResItem == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
+               PVR_DBG_BREAK;
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+#ifdef DEBUG 
+       PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+       if (psNewResManContext != IMG_NULL)
+       {
+               
+               List_RESMAN_ITEM_Remove(psResItem);
+
+               
+               List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
+
+       }
+       else
+       {
+               eError = FreeResourceByPtr(psResItem, IMG_FALSE);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: failed to free resource by pointer"));
+                       return eError;
+               }
+       }
+
+       return eError;
+}
+
+static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+       RESMAN_ITEM             *psItem;
+
+       psItem = va_arg(va, RESMAN_ITEM*);
+
+       return (IMG_BOOL)(psCurItem == psItem);
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT      psResManContext,
+                                                                                                 RESMAN_ITEM           *psItem)
+{
+       PVRSRV_ERROR    eResult;
+
+       PVR_ASSERT(psResManContext != IMG_NULL);
+       PVR_ASSERT(psItem != IMG_NULL);
+
+       if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
+               PVR_DBG_BREAK;
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+#ifdef DEBUG   
+       PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+       
+       ACQUIRE_SYNC_OBJ;
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+                       (IMG_UINTPTR_T)psItem, (IMG_UINTPTR_T)psItem->psNext));
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "FindResourceByPtr: Resource Ctx 0x%x, Type 0x%x, Addr 0x%x, "
+                       "Param 0x%x, FnCall %08X, Flags 0x%x",
+                       (IMG_UINTPTR_T)psResManContext,
+                       psItem->ui32ResType,
+                       (IMG_UINTPTR_T)psItem->pvParam,
+                       psItem->ui32Param,
+                       (IMG_UINTPTR_T)psItem->pfnFreeResource,
+                       psItem->ui32Flags));
+
+       
+       if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
+                                                                               &ResManFindResourceByPtr_AnyVaCb,
+                                                                               psItem))
+       {
+               eResult = PVRSRV_OK;
+       }
+       else
+       {
+               eResult = PVRSRV_ERROR_NOT_OWNER;
+       }
+
+       
+       RELEASE_SYNC_OBJ;
+
+       return eResult;
+}
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM      *psItem,
+                                                                         IMG_BOOL              bExecuteCallback)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psItem != IMG_NULL);
+
+       if (psItem == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+#ifdef DEBUG   
+       PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+                       (IMG_UINTPTR_T)psItem, (IMG_UINTPTR_T)psItem->psNext));
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "FreeResourceByPtr: Type 0x%x, Addr 0x%x, "
+                       "Param 0x%x, FnCall %08X, Flags 0x%x",
+                       psItem->ui32ResType,
+                       (IMG_UINTPTR_T)psItem->pvParam, psItem->ui32Param,
+                       (IMG_UINTPTR_T)psItem->pfnFreeResource, psItem->ui32Flags));
+
+       
+       List_RESMAN_ITEM_Remove(psItem);
+
+
+       
+       RELEASE_SYNC_OBJ;
+
+       
+       if (bExecuteCallback)
+       {
+               eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
+               }
+       }
+
+       
+       ACQUIRE_SYNC_OBJ;
+
+       
+       eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR freeing resource list item memory"));
+       }
+
+       return(eError);
+}
+
+static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+       IMG_UINT32 ui32SearchCriteria;
+       IMG_UINT32 ui32ResType;
+       IMG_PVOID pvParam;
+       IMG_UINT32 ui32Param;
+
+       ui32SearchCriteria = va_arg(va, IMG_UINT32);
+       ui32ResType = va_arg(va, IMG_UINT32);
+       pvParam = va_arg(va, IMG_PVOID);
+       ui32Param = va_arg(va, IMG_UINT32);
+
+       
+       if(
+       
+               (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+               (psCurItem->ui32ResType == ui32ResType))
+       &&
+       
+               (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+                        (psCurItem->pvParam == pvParam))
+       &&
+       
+               (((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+                        (psCurItem->ui32Param == ui32Param))
+               )
+       {
+               return psCurItem;
+       }
+       else
+       {
+               return IMG_NULL;
+       }
+}
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT     psResManContext,
+                                                                                  IMG_UINT32           ui32SearchCriteria,
+                                                                                  IMG_UINT32           ui32ResType,
+                                                                                  IMG_PVOID            pvParam,
+                                                                                  IMG_UINT32           ui32Param,
+                                                                                  IMG_BOOL                     bExecuteCallback)
+{
+       PRESMAN_ITEM    psCurItem;
+       PVRSRV_ERROR    eError = PVRSRV_OK;
+
+       
+       
+       while((psCurItem = (PRESMAN_ITEM)
+                               List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
+                                                                               &FreeResourceByCriteria_AnyVaCb,
+                                                                               ui32SearchCriteria,
+                                                                               ui32ResType,
+                                                                               pvParam,
+                                                                               ui32Param)) != IMG_NULL
+                       && eError == PVRSRV_OK)
+       {
+               eError = FreeResourceByPtr(psCurItem, bExecuteCallback);
+       }
+
+       return eError;
+}
+
+
+#ifdef DEBUG
+static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
+{
+       PRESMAN_ITEM    psCurItem, *ppsThisItem;
+       PRESMAN_CONTEXT psCurContext, *ppsThisContext;
+
+       
+       if (psResList == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
+               return;
+       }
+
+       psCurContext = psResList->psContextList;
+       ppsThisContext = &psResList->psContextList;
+
+       
+       while(psCurContext != IMG_NULL)
+       {
+               
+               PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
+               if (psCurContext->ppsThis != ppsThisContext)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                       "psCC=%08X psCC->ppsThis=%08X psCC->psNext=%08X ppsTC=%08X",
+                                       (IMG_UINTPTR_T)psCurContext,
+                                       (IMG_UINTPTR_T)psCurContext->ppsThis,
+                                       (IMG_UINTPTR_T)psCurContext->psNext,
+                                       (IMG_UINTPTR_T)ppsThisContext));
+                       PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
+               }
+
+               
+               psCurItem = psCurContext->psResItemList;
+               ppsThisItem = &psCurContext->psResItemList;
+               while(psCurItem != IMG_NULL)
+               {
+                       
+                       PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
+                       if (psCurItem->ppsThis != ppsThisItem)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING,
+                                               "psCurItem=%08X psCurItem->ppsThis=%08X psCurItem->psNext=%08X ppsThisItem=%08X",
+                                               (IMG_UINTPTR_T)psCurItem,
+                                               (IMG_UINTPTR_T)psCurItem->ppsThis,
+                                               (IMG_UINTPTR_T)psCurItem->psNext,
+                                               (IMG_UINTPTR_T)ppsThisItem));
+                               PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+                       }
+
+                       
+                       ppsThisItem = &psCurItem->psNext;
+                       psCurItem = psCurItem->psNext;
+               }
+
+               
+               ppsThisContext = &psCurContext->psNext;
+               psCurContext = psCurContext->psNext;
+       }
+}
+#endif 
+
+#ifdef RES_MAN_EXTEND
+
+IMG_PVOID PVRSRVGetResData(PRESMAN_ITEM psResItem)
+{
+       if (psResItem)
+               return psResItem->pvParam;
+       else
+               return IMG_NULL;
+}
+
+static IMG_VOID* PickResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+       IMG_UINT32 ui32SearchCriteria;
+       IMG_UINT32 ui32ResType;
+       IMG_PVOID pvParam;
+       IMG_UINT32 ui32Param;
+
+       ui32SearchCriteria = va_arg(va, IMG_UINT32);
+       ui32ResType = va_arg(va, IMG_UINT32);
+       pvParam = va_arg(va, IMG_PVOID);
+       ui32Param = va_arg(va, IMG_UINT32);
+
+
+       if(
+
+               (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+               (psCurItem->ui32ResType == ui32ResType))
+       &&
+
+               (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+                        (psCurItem->pvParam == pvParam))
+       &&
+
+               (((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+                        (psCurItem->ui32Param == ui32Param))
+               )
+       {
+               return psCurItem;
+       }
+       else
+       {
+               return IMG_NULL;
+       }
+}
+
+PVRSRV_ERROR PVRSRVResManAnyByCriteria(PRESMAN_CONTEXT psResManContext,
+                                       IMG_UINT32 ui32SearchCriteria,
+                                       IMG_UINT32              ui32ResType,
+                                       IMG_PVOID               pvParam,
+                                       IMG_UINT32              ui32Param,
+                                       PVRSRV_ERROR(*pfnCallBack)(PRESMAN_ITEM psRes, va_list va), ...)
+{
+       PRESMAN_ITEM    psCurItem;
+       PVRSRV_ERROR    eError = PVRSRV_OK;
+       va_list ap;
+
+       psCurItem = psResManContext->psResItemList;
+       while((psCurItem = (PRESMAN_ITEM)
+                               List_RESMAN_ITEM_Any_va(psCurItem,
+                                                       &PickResourceByCriteria_AnyVaCb,
+                                                       ui32SearchCriteria,
+                                                       ui32ResType,
+                                                       pvParam,
+                                                       ui32Param)) != IMG_NULL
+                       && eError == PVRSRV_OK)
+       {
+               va_start(ap, pfnCallBack);
+               eError = pfnCallBack(psCurItem, ap);
+               va_end(ap);
+               psCurItem = psCurItem->psNext;
+       }
+
+       return eError;
+}
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/.gitignore b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/.gitignore
new file mode 100644 (file)
index 0000000..2f89523
--- /dev/null
@@ -0,0 +1,5 @@
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+*.o
+*.o.cmd
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/mmu.c b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/mmu.c
new file mode 100644 (file)
index 0000000..ea480e0
--- /dev/null
@@ -0,0 +1,2990 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "mmu.h"
+#include "sgxconfig.h"
+#include "sgx_bridge_km.h"
+#include "pdump_osfunc.h"
+
+#define UINT32_MAX_VALUE       0xFFFFFFFFUL
+
+#define SGX_MAX_PD_ENTRIES     (1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT))
+
+typedef struct _MMU_PT_INFO_
+{
+       
+       IMG_VOID *hPTPageOSMemHandle;
+       IMG_CPU_VIRTADDR PTPageCpuVAddr;
+       IMG_UINT32 ui32ValidPTECount;
+} MMU_PT_INFO;
+
+struct _MMU_CONTEXT_
+{
+       
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       
+       IMG_CPU_VIRTADDR pvPDCpuVAddr;
+       IMG_DEV_PHYADDR sPDDevPAddr;
+
+       IMG_VOID *hPDOSMemHandle;
+
+       
+       MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES];
+
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+
+#if defined(PDUMP)
+       IMG_UINT32 ui32PDumpMMUContextID;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+       IMG_BOOL bPDumpActive;
+#endif
+#endif
+
+       struct _MMU_CONTEXT_ *psNext;
+};
+
+struct _MMU_HEAP_
+{
+       
+       MMU_CONTEXT                     *psMMUContext;
+
+       
+
+       
+       IMG_UINT32                      ui32PDBaseIndex;
+       
+       IMG_UINT32                      ui32PageTableCount;
+       
+       IMG_UINT32                      ui32PTETotal;
+       
+       IMG_UINT32                      ui32PDEPageSizeCtrl;
+
+       
+
+       
+       IMG_UINT32                      ui32DataPageSize;
+       
+       IMG_UINT32                      ui32DataPageBitWidth;
+       
+       IMG_UINT32                      ui32DataPageMask;
+
+       
+
+       
+       IMG_UINT32                      ui32PTShift;
+       
+       IMG_UINT32                      ui32PTBitWidth;
+       
+       IMG_UINT32                      ui32PTMask;
+       
+       IMG_UINT32                      ui32PTSize;
+       
+       IMG_UINT32                      ui32PTECount;
+
+       
+
+       
+       IMG_UINT32                      ui32PDShift;
+       
+       IMG_UINT32                      ui32PDBitWidth;
+       
+       IMG_UINT32                      ui32PDMask;
+
+       
+
+       RA_ARENA *psVMArena;
+       DEV_ARENA_DESCRIPTOR *psDevArena;
+#if defined(PDUMP)
+       PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+};
+
+
+
+#if defined (SUPPORT_SGX_MMU_DUMMY_PAGE)
+#define DUMMY_DATA_PAGE_SIGNATURE      0xDEADBEEF
+#endif
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables    (MMU_HEAP *pMMUHeap,
+                                        IMG_DEV_VIRTADDR DevVAddr,
+                                        IMG_SIZE_T uSize,
+                                        IMG_BOOL bForUnmap,
+                                        IMG_HANDLE hUniqueTag);
+#endif 
+
+#define PAGE_TEST                                      0
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr);
+#endif
+
+#define PT_DEBUG 0
+#if PT_DEBUG
+static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+       IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+       IMG_UINT32 i;
+
+       
+       for(i = 0; i < 1024; i += 8)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                                "%08X %08X %08X %08X %08X %08X %08X %08X\n",
+                                p[i + 0], p[i + 1], p[i + 2], p[i + 3],
+                                p[i + 4], p[i + 5], p[i + 6], p[i + 7]));
+       }
+}
+
+static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+       IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr;
+       IMG_UINT32 i, ui32Count = 0;
+
+       
+       for(i = 0; i < 1024; i++)
+               if(p[i] & SGX_MMU_PTE_VALID)
+                       ui32Count++;
+
+       if(psPTInfoList->ui32ValidPTECount != ui32Count)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "ui32ValidPTECount: %u ui32Count: %u\n",
+                                psPTInfoList->ui32ValidPTECount, ui32Count));
+               DumpPT(psPTInfoList);
+               BUG();
+       }
+}
+#else 
+static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+       PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+
+static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+       PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif 
+
+
+IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMUHeap)
+{
+       switch(pMMUHeap->psDevArena->DevMemHeapType)
+       {
+               case DEVICE_MEMORY_HEAP_SHARED :
+               case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+                       return IMG_TRUE;
+               case DEVICE_MEMORY_HEAP_PERCONTEXT :
+               case DEVICE_MEMORY_HEAP_KERNEL :
+                       return IMG_FALSE;
+               default:
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_IsHeapShared: ERROR invalid heap type"));
+                       return IMG_FALSE;
+               }
+       }
+}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+       IMG_UINT32 ui32RegVal;
+       IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+       
+
+
+       ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL);
+
+       OSWriteHWReg(pvRegsBaseKM,
+                               EUR_CR_BIF_CTRL,
+                               ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+       
+       PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+}
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+       IMG_UINT32 ui32RegVal;
+       IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+       
+
+
+
+       OSWriteHWReg(pvRegsBaseKM,
+                               EUR_CR_BIF_CTRL,
+                               ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+       
+       PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, 0);
+}
+#endif
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+static IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+       #if defined(SGX_FEATURE_MP)
+       psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
+       #else
+       
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       #endif 
+}
+#endif 
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+       psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
+       #if defined(SGX_FEATURE_SYSTEM_CACHE)
+       MMU_InvalidateSystemLevelCache(psDevInfo);
+       #endif 
+}
+
+
+static IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+       psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT;
+       #if defined(SGX_FEATURE_SYSTEM_CACHE)
+       MMU_InvalidateSystemLevelCache(psDevInfo);
+       #endif 
+}
+
+
+static IMG_BOOL
+_AllocPageTableMemory (MMU_HEAP *pMMUHeap,
+                                               MMU_PT_INFO *psPTInfoList,
+                                               IMG_DEV_PHYADDR *psDevPAddr)
+{
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_CPU_PHYADDR sCpuPAddr;
+
+       
+
+
+       if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+       {
+               
+               if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                  pMMUHeap->ui32PTSize,
+                                                  SGX_MMU_PAGE_SIZE,
+                                                  (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
+                                                  &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed"));
+                       return IMG_FALSE;
+               }
+
+               
+               if(psPTInfoList->PTPageCpuVAddr)
+               {
+                       sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
+                                                                                 psPTInfoList->PTPageCpuVAddr);
+               }
+               else
+               {
+                       
+                       sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0);
+               }
+
+               sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+       }
+       else
+       {
+               IMG_SYS_PHYADDR sSysPAddr;
+
+               
+
+
+               
+               if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena,
+                                       SGX_MMU_PAGE_SIZE,
+                                       IMG_NULL,
+                                       IMG_NULL,
+                                       0,
+                                       SGX_MMU_PAGE_SIZE,
+                                       0,
+                                       &(sSysPAddr.uiAddr))!= IMG_TRUE)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to RA_Alloc failed"));
+                       return IMG_FALSE;
+               }
+
+               
+               sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+               
+               psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+                                                                                                       SGX_MMU_PAGE_SIZE,
+                                                                                                       PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                                                                       &psPTInfoList->hPTPageOSMemHandle);
+               if(!psPTInfoList->PTPageCpuVAddr)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR failed to map page tables"));
+                       return IMG_FALSE;
+               }
+
+               
+               sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+               #if PAGE_TEST
+               PageTest(psPTInfoList->PTPageCpuVAddr, sDevPAddr);
+               #endif
+       }
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+       {
+               IMG_UINT32 *pui32Tmp;
+               IMG_UINT32 i;
+
+               pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+               
+               for(i=0; i<pMMUHeap->ui32PTECount; i++)
+               {
+                       pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+                                               | SGX_MMU_PTE_VALID;
+               }
+       }
+#else
+       
+       OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize);
+#endif
+
+#if defined(PDUMP)
+       {
+               IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+       
+               ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+       
+               PDUMPMALLOCPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, psPTInfoList->hPTPageOSMemHandle, 0, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
+
+               PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfoList->hPTPageOSMemHandle, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+       }
+#endif
+
+       
+       *psDevPAddr = sDevPAddr;
+
+       return IMG_TRUE;
+}
+
+
+static IMG_VOID
+_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
+{
+       
+
+
+
+       if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+       {
+               
+               OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                         pMMUHeap->ui32PTSize,
+                                         psPTInfoList->PTPageCpuVAddr,
+                                         psPTInfoList->hPTPageOSMemHandle);
+       }
+       else
+       {
+               IMG_SYS_PHYADDR sSysPAddr;
+               IMG_CPU_PHYADDR sCpuPAddr;
+
+               
+               sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle, 
+                                                                         psPTInfoList->PTPageCpuVAddr);
+               sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr);
+
+               
+               
+               OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr,
+                         SGX_MMU_PAGE_SIZE,
+                         PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                         psPTInfoList->hPTPageOSMemHandle);
+
+               
+
+
+               RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+       }
+}
+
+
+
+static IMG_VOID
+_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT)
+{
+       IMG_UINT32 *pui32PDEntry;
+       IMG_UINT32 i;
+       IMG_UINT32 ui32PDIndex;
+       SYS_DATA *psSysData;
+       MMU_PT_INFO **ppsPTInfoList;
+
+       SysAcquireData(&psSysData);
+
+       
+       ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+       
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+       {
+#if PT_DEBUG
+               if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0)
+               {
+                       DumpPT(ppsPTInfoList[ui32PTIndex]);
+                       
+               }
+#endif
+
+               
+               PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0);
+       }
+
+#if defined(PDUMP)
+       {
+               IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+               ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+       
+       PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+       if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
+       {
+                       PDUMPFREEPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, ppsPTInfoList[ui32PTIndex]->hPTPageOSMemHandle, ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
+       }
+       }
+#endif
+
+       switch(pMMUHeap->psDevArena->DevMemHeapType)
+       {
+               case DEVICE_MEMORY_HEAP_SHARED :
+               case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+               {
+                       
+                       MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+                       while(psMMUContext)
+                       {
+                               
+                               pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+                               pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+                               
+                               pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+                                                                                       >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+                                                                                       | SGX_MMU_PDE_PAGE_SIZE_4K
+                                                                                       | SGX_MMU_PDE_VALID;
+#else
+                               
+                               if(bOSFreePT)
+                               {
+                                       pui32PDEntry[ui32PTIndex] = 0;
+                               }
+#endif
+                       #if defined(PDUMP)
+
+                       #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+                               if(psMMUContext->bPDumpActive)
+                       #endif
+                               {
+                               PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+                               }
+                       #endif
+                               
+                               psMMUContext = psMMUContext->psNext;
+                       }
+                       break;
+               }
+               case DEVICE_MEMORY_HEAP_PERCONTEXT :
+               case DEVICE_MEMORY_HEAP_KERNEL :
+               {
+                       
+                       pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+                       pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+                       
+                       pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+                                                                               >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+                                                                               | SGX_MMU_PDE_PAGE_SIZE_4K
+                                                                               | SGX_MMU_PDE_VALID;
+#else
+                       
+                       if(bOSFreePT)
+                       {
+                               pui32PDEntry[ui32PTIndex] = 0;
+                       }
+#endif
+
+                       
+                       PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+                       break;
+               }
+               default:
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "_DeferredFreePagetable: ERROR invalid heap type"));
+                       return;
+               }
+       }
+
+       
+       if(ppsPTInfoList[ui32PTIndex] != IMG_NULL)
+       {
+               if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL)
+               {
+                       IMG_PUINT32 pui32Tmp;
+
+                       pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr;
+
+                       
+                       for(i=0;
+                               (i<pMMUHeap->ui32PTETotal) && (i<pMMUHeap->ui32PTECount);
+                                i++)
+                       {
+                               pui32Tmp[i] = 0;
+                       }
+
+                       
+
+                       if(bOSFreePT)
+                       {
+                               _FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]);
+                       }
+
+                       
+
+
+                       pMMUHeap->ui32PTETotal -= i;
+               }
+               else
+               {
+                       
+                       pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount;
+               }
+
+               if(bOSFreePT)
+               {
+                       
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof(MMU_PT_INFO),
+                                               ppsPTInfoList[ui32PTIndex],
+                                               IMG_NULL);
+                       ppsPTInfoList[ui32PTIndex] = IMG_NULL;
+               }
+       }
+       else
+       {
+               
+               pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount;
+       }
+
+       PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+}
+
+static IMG_VOID
+_DeferredFreePageTables (MMU_HEAP *pMMUHeap)
+{
+       IMG_UINT32 i;
+#if defined(PDUMP)
+       PDUMPCOMMENT("Free PTs (MMU Context ID == %u, PDBaseIndex == %u, PT count == 0x%x)",
+                       pMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+                       pMMUHeap->ui32PDBaseIndex,
+                       pMMUHeap->ui32PageTableCount);
+#endif
+       for(i=0; i<pMMUHeap->ui32PageTableCount; i++)
+       {
+               _DeferredFreePageTable(pMMUHeap, i, IMG_TRUE);
+       }
+       MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+}
+
+
+static IMG_BOOL
+_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+       IMG_UINT32 ui32PageTableCount;
+       IMG_UINT32 ui32PDIndex;
+       IMG_UINT32 i;
+       IMG_UINT32 *pui32PDEntry;
+       MMU_PT_INFO **ppsPTInfoList;
+       SYS_DATA *psSysData;
+       IMG_DEV_VIRTADDR sHighDevVAddr;
+
+       
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
+       PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE));
+#endif
+
+       
+       SysAcquireData(&psSysData);
+
+       
+       ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+       
+       
+       if((UINT32_MAX_VALUE - DevVAddr.uiAddr)
+               < (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask))
+       {
+               
+               sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
+       }
+       else
+       {
+               sHighDevVAddr.uiAddr = DevVAddr.uiAddr
+                                                               + ui32Size
+                                                               + pMMUHeap->ui32DataPageMask
+                                                               + pMMUHeap->ui32PTMask;
+       }
+
+       ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+       ui32PageTableCount -= ui32PDIndex;
+
+       
+       pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+       pui32PDEntry += ui32PDIndex;
+
+       
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+#if defined(PDUMP)
+       PDUMPCOMMENT("Alloc PTs (MMU Context ID == %u, PDBaseIndex == %u, Size == 0x%x)",
+                       pMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+                       pMMUHeap->ui32PDBaseIndex,
+                       ui32Size);
+       PDUMPCOMMENT("Alloc page table (page count == %08X)", ui32PageTableCount);
+       PDUMPCOMMENT("Page directory mods (page count == %08X)", ui32PageTableCount);
+#endif
+       
+       for(i=0; i<ui32PageTableCount; i++)
+       {
+               if(ppsPTInfoList[i] == IMG_NULL)
+               {
+                       OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                                sizeof (MMU_PT_INFO),
+                                                (IMG_VOID **)&ppsPTInfoList[i], IMG_NULL,
+                                                "MMU Page Table Info");
+                       if (ppsPTInfoList[i] == IMG_NULL)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to OSAllocMem failed"));
+                               return IMG_FALSE;
+                       }
+                       OSMemSet (ppsPTInfoList[i], 0, sizeof(MMU_PT_INFO));
+               }
+
+               if(ppsPTInfoList[i]->hPTPageOSMemHandle == IMG_NULL
+               && ppsPTInfoList[i]->PTPageCpuVAddr == IMG_NULL)
+               {
+                       IMG_DEV_PHYADDR sDevPAddr;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+                       IMG_UINT32 *pui32Tmp;
+                       IMG_UINT32 j;
+#else
+                       
+                       PVR_ASSERT(pui32PDEntry[i] == 0);
+#endif
+
+                       if(_AllocPageTableMemory (pMMUHeap, ppsPTInfoList[i], &sDevPAddr) != IMG_TRUE)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to _AllocPageTableMemory failed"));
+                               return IMG_FALSE;
+                       }
+
+                       switch(pMMUHeap->psDevArena->DevMemHeapType)
+                       {
+                               case DEVICE_MEMORY_HEAP_SHARED :
+                               case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+                               {
+                                       
+                                       MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+                                       while(psMMUContext)
+                                       {
+                                               
+                                               pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+                                               pui32PDEntry += ui32PDIndex;
+
+                                               
+                                               pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+                                                                               | pMMUHeap->ui32PDEPageSizeCtrl
+                                                                               | SGX_MMU_PDE_VALID;
+
+                                               #if defined(PDUMP)
+
+                                               #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+                                               if(psMMUContext->bPDumpActive)
+                                               #endif
+                                               {
+                                               
+                                               PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+                                               }
+                                               #endif
+
+                                               
+                                               psMMUContext = psMMUContext->psNext;
+                                       }
+                                       break;
+                               }
+                               case DEVICE_MEMORY_HEAP_PERCONTEXT :
+                               case DEVICE_MEMORY_HEAP_KERNEL :
+                               {
+                                       
+                                       pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+                                                                       | pMMUHeap->ui32PDEPageSizeCtrl
+                                                                       | SGX_MMU_PDE_VALID;
+
+                                       
+                                       PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+                                       break;
+                               }
+                               default:
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR invalid heap type"));
+                                       return IMG_FALSE;
+                               }
+                       }
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+                       
+
+
+
+                       MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+               }
+               else
+               {
+                       
+                       PVR_ASSERT(pui32PDEntry[i] != 0);
+               }
+       }
+
+       #if defined(SGX_FEATURE_SYSTEM_CACHE)
+       MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo);
+       #endif 
+
+       return IMG_TRUE;
+}
+
+
+#if defined(PDUMP)
+IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext)
+{
+       BM_CONTEXT *pBMContext = hDevMemContext;
+       PVR_ASSERT(pBMContext);
+       return pBMContext->psMMUContext->ui32PDumpMMUContextID;
+}
+
+static IMG_VOID MMU_SetPDumpAttribs(PDUMP_MMU_ATTRIB *psMMUAttrib,
+       PVRSRV_DEVICE_NODE *psDeviceNode,
+       IMG_UINT32 ui32DataPageMask,
+       IMG_UINT32 ui32PTSize)
+{
+       
+       psMMUAttrib->sDevId = psDeviceNode->sDevId;
+       
+       psMMUAttrib->pszPDRegRegion = IMG_NULL;
+       psMMUAttrib->ui32DataPageMask = ui32DataPageMask;
+       
+       psMMUAttrib->ui32PTEValid = SGX_MMU_PTE_VALID;
+       psMMUAttrib->ui32PTSize = ui32PTSize;
+       psMMUAttrib->ui32PTEAlignShift = SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+       
+       psMMUAttrib->ui32PDEMask = SGX_MMU_PDE_ADDR_MASK;
+       psMMUAttrib->ui32PDEAlignShift = SGX_MMU_PDE_ADDR_ALIGNSHIFT;
+}
+#endif 
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+       IMG_UINT32 *pui32Tmp;
+       IMG_UINT32 i;
+       IMG_CPU_VIRTADDR pvPDCpuVAddr;
+       IMG_DEV_PHYADDR sPDDevPAddr;
+       IMG_CPU_PHYADDR sCpuPAddr;
+       MMU_CONTEXT *psMMUContext;
+       IMG_HANDLE hPDOSMemHandle;
+       SYS_DATA *psSysData;
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+#if defined(PDUMP)
+       PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+       PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Initialise"));
+
+       SysAcquireData(&psSysData);
+#if defined(PDUMP)
+       
+       
+       MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+                                               SGX_MMU_PAGE_MASK,
+                                               SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+       OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                sizeof (MMU_CONTEXT),
+                                (IMG_VOID **)&psMMUContext, IMG_NULL,
+                                "MMU Context");
+       if (psMMUContext == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT));
+
+       
+       psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+       psMMUContext->psDevInfo = psDevInfo;
+
+       
+       psMMUContext->psDeviceNode = psDeviceNode;
+
+       
+       if(psDeviceNode->psLocalDevMemArena == IMG_NULL)
+       {
+               if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                       SGX_MMU_PAGE_SIZE,
+                                                       SGX_MMU_PAGE_SIZE,
+                                                       &pvPDCpuVAddr,
+                                                       &hPDOSMemHandle) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+                       return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+               }
+
+               if(pvPDCpuVAddr)
+               {
+                       sCpuPAddr = OSMapLinToCPUPhys(hPDOSMemHandle,
+                                                                                 pvPDCpuVAddr);
+               }
+               else
+               {
+                       
+                       sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
+               }
+               sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+               #if PAGE_TEST
+               PageTest(pvPDCpuVAddr, sPDDevPAddr);
+               #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+               
+               if(!psDevInfo->pvMMUContextList)
+               {
+                       
+                       if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                               SGX_MMU_PAGE_SIZE,
+                                                               SGX_MMU_PAGE_SIZE,
+                                                               &psDevInfo->pvDummyPTPageCpuVAddr,
+                                                               &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+                               return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+                       }
+
+                       if(psDevInfo->pvDummyPTPageCpuVAddr)
+                       {
+                               sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+                                                                                         psDevInfo->pvDummyPTPageCpuVAddr);
+                       }
+                       else
+                       {
+                               
+                               sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0);
+                       }
+                       psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+                       
+                       if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                               SGX_MMU_PAGE_SIZE,
+                                                               SGX_MMU_PAGE_SIZE,
+                                                               &psDevInfo->pvDummyDataPageCpuVAddr,
+                                                               &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+                               return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+                       }
+
+                       if(psDevInfo->pvDummyDataPageCpuVAddr)
+                       {
+                               sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+                                                                                         psDevInfo->pvDummyDataPageCpuVAddr);
+                       }
+                       else
+                       {
+                               sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyDataPageOSMemHandle, 0);
+                       }
+                       psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+               }
+#endif 
+       }
+       else
+       {
+               IMG_SYS_PHYADDR sSysPAddr;
+
+               
+               if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+                                       SGX_MMU_PAGE_SIZE,
+                                       IMG_NULL,
+                                       IMG_NULL,
+                                       0,
+                                       SGX_MMU_PAGE_SIZE,
+                                       0,
+                                       &(sSysPAddr.uiAddr))!= IMG_TRUE)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+                       return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+               }
+
+               
+               sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+               sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+               pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+                                                                               SGX_MMU_PAGE_SIZE,
+                                                                               PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                                               &hPDOSMemHandle);
+               if(!pvPDCpuVAddr)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+                       return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+               }
+
+               #if PAGE_TEST
+               PageTest(pvPDCpuVAddr, sPDDevPAddr);
+               #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+               
+               if(!psDevInfo->pvMMUContextList)
+               {
+                       
+                       if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+                                               SGX_MMU_PAGE_SIZE,
+                                               IMG_NULL,
+                                               IMG_NULL,
+                                               0,
+                                               SGX_MMU_PAGE_SIZE,
+                                               0,
+                                               &(sSysPAddr.uiAddr))!= IMG_TRUE)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+                               return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+                       }
+
+                       
+                       sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+                       psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+                       psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+                                                                                                                               SGX_MMU_PAGE_SIZE,
+                                                                                                                               PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                                                                                               &psDevInfo->hDummyPTPageOSMemHandle);
+                       if(!psDevInfo->pvDummyPTPageCpuVAddr)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+                               return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+                       }
+
+                       
+                       if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+                                               SGX_MMU_PAGE_SIZE,
+                                               IMG_NULL,
+                                               IMG_NULL,
+                                               0,
+                                               SGX_MMU_PAGE_SIZE,
+                                               0,
+                                               &(sSysPAddr.uiAddr))!= IMG_TRUE)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+                               return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+                       }
+
+                       
+                       sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+                       psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+                       psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+                                                                                                                               SGX_MMU_PAGE_SIZE,
+                                                                                                                               PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                                                                                               &psDevInfo->hDummyDataPageOSMemHandle);
+                       if(!psDevInfo->pvDummyDataPageCpuVAddr)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+                               return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+                       }
+               }
+#endif 
+       }
+
+#if defined(PDUMP)
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+       {
+               PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+               if(psPerProc == IMG_NULL)
+               {
+
+                       psMMUContext->bPDumpActive = IMG_TRUE;
+               }
+               else
+               {
+                       psMMUContext->bPDumpActive = psPerProc->bPDumpActive;
+               }
+       }
+#endif
+       
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+       PDUMPCOMMENT("Alloc page directory for new MMU context (PDDevPAddr == 0x%08x)",
+                       sPDDevPAddr.uiAddr);
+#else
+       PDUMPCOMMENT("Alloc page directory for new MMU context, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)",
+                       sPDDevPAddr.uiHighAddr, sPDDevPAddr.uiAddr);
+#endif
+       PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDOSMemHandle, 0, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+#endif 
+#ifdef SUPPORT_SGX_MMU_BYPASS
+       EnableHostAccess(psMMUContext);
+#endif
+
+       if (pvPDCpuVAddr)
+       {
+               pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid"));
+               return PVRSRV_ERROR_INVALID_CPU_ADDR;
+       }
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+       
+       for(i=0; i<SGX_MMU_PD_SIZE; i++)
+       {
+               pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+                                       | SGX_MMU_PDE_PAGE_SIZE_4K
+                                       | SGX_MMU_PDE_VALID;
+       }
+
+       if(!psDevInfo->pvMMUContextList)
+       {
+               
+
+
+               pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr;
+               for(i=0; i<SGX_MMU_PT_SIZE; i++)
+               {
+                       pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+                                               | SGX_MMU_PTE_VALID;
+               }
+               
+               PDUMPCOMMENT("Dummy Page table contents");
+               PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hDummyPTOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+               
+
+               pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr;
+               for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++)
+               {
+                       pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE;
+               }
+               
+               PDUMPCOMMENT("Dummy Data Page contents");
+               PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+       }
+#else 
+       
+       for(i=0; i<SGX_MMU_PD_SIZE; i++)
+       {
+               
+               pui32Tmp[i] = 0;
+       }
+#endif 
+
+#if defined(PDUMP)
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+       if(psMMUContext->bPDumpActive)
+#endif
+       {
+       
+       PDUMPCOMMENT("Page directory contents");
+               PDUMPPDENTRIES(&sMMUAttrib, hPDOSMemHandle, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+       }
+
+       
+       {
+               PVRSRV_ERROR eError;
+               
+               IMG_UINT32 ui32MMUType = 1;
+
+               #if defined(SGX_FEATURE_36BIT_MMU)
+                       ui32MMUType = 3;
+               #else
+                       #if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+                               ui32MMUType = 2;
+                       #endif
+               #endif
+
+               eError = PDumpSetMMUContext(PVRSRV_DEVICE_TYPE_SGX,
+                                                                       psDeviceNode->sDevId.pszPDumpDevName,
+                                                                       &psMMUContext->ui32PDumpMMUContextID,
+                                                                       ui32MMUType,
+                                                                       PDUMP_PT_UNIQUETAG,
+                                                                       hPDOSMemHandle,
+                                                                       pvPDCpuVAddr);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to PDumpSetMMUContext failed"));
+                       return eError;
+               }
+       }
+
+       
+       PDUMPCOMMENT("Set MMU context complete (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+#endif
+
+       
+       psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
+       psMMUContext->sPDDevPAddr = sPDDevPAddr;
+       psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
+
+       
+       *ppsMMUContext = psMMUContext;
+
+       
+       *psPDDevPAddr = sPDDevPAddr;
+
+       
+       psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+       psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext;
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+       DisableHostAccess(psMMUContext);
+#endif
+
+       return PVRSRV_OK;
+}
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext)
+{
+       IMG_UINT32 *pui32Tmp, i;
+       SYS_DATA *psSysData;
+       MMU_CONTEXT **ppsMMUContext;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+       PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
+       MMU_CONTEXT *psMMUContextList = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+#endif
+
+       SysAcquireData(&psSysData);
+
+#if defined(PDUMP)
+       
+       PDUMPCOMMENT("Clear MMU context (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+       PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->psDeviceNode->sDevId.pszPDumpDevName, psMMUContext->ui32PDumpMMUContextID, 2);
+
+       
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+       PDUMPCOMMENT("Free page directory (PDDevPAddr == 0x%08x)",
+                       psMMUContext->sPDDevPAddr.uiAddr);
+#else
+       PDUMPCOMMENT("Free page directory, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)",
+                       psMMUContext->sPDDevPAddr.uiHighAddr, psMMUContext->sPDDevPAddr.uiAddr);
+#endif
+#endif 
+
+       PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psMMUContext->hPDOSMemHandle, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+       PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyPTPageOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+       PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+#endif
+
+       pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr;
+
+       
+       for(i=0; i<SGX_MMU_PD_SIZE; i++)
+       {
+               
+               pui32Tmp[i] = 0;
+       }
+
+       
+
+
+
+       if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL)
+       {
+               OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                               SGX_MMU_PAGE_SIZE,
+                                               psMMUContext->pvPDCpuVAddr,
+                                               psMMUContext->hPDOSMemHandle);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+               
+               if(!psMMUContextList->psNext)
+               {
+                       OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                       SGX_MMU_PAGE_SIZE,
+                                                       psDevInfo->pvDummyPTPageCpuVAddr,
+                                                       psDevInfo->hDummyPTPageOSMemHandle);
+                       OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                       SGX_MMU_PAGE_SIZE,
+                                                       psDevInfo->pvDummyDataPageCpuVAddr,
+                                                       psDevInfo->hDummyDataPageOSMemHandle);
+               }
+#endif
+       }
+       else
+       {
+               IMG_SYS_PHYADDR sSysPAddr;
+               IMG_CPU_PHYADDR sCpuPAddr;
+
+               
+               sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->hPDOSMemHandle,
+                                                                         psMMUContext->pvPDCpuVAddr);
+               sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+               
+               OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr,
+                                                       SGX_MMU_PAGE_SIZE,
+                            PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                       psMMUContext->hPDOSMemHandle);
+               
+               RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+               
+               if(!psMMUContextList->psNext)
+               {
+                       
+                       sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+                                                                                 psDevInfo->pvDummyPTPageCpuVAddr);
+                       sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+                       
+                       OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr,
+                                                               SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                               psDevInfo->hDummyPTPageOSMemHandle);
+                       
+                       RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+                       
+                       sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyDataPageOSMemHandle,
+                                                                                 psDevInfo->pvDummyDataPageCpuVAddr);
+                       sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+                       
+                       OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr,
+                                                               SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                               psDevInfo->hDummyDataPageOSMemHandle);
+                       
+                       RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+               }
+#endif
+       }
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise"));
+
+       
+       ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList;
+       while(*ppsMMUContext)
+       {
+               if(*ppsMMUContext == psMMUContext)
+               {
+                       
+                       *ppsMMUContext = psMMUContext->psNext;
+                       break;
+               }
+
+               
+               ppsMMUContext = &((*ppsMMUContext)->psNext);
+       }
+
+       
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL);
+       
+}
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
+{
+       IMG_UINT32 *pui32PDCpuVAddr = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
+       IMG_UINT32 *pui32KernelPDCpuVAddr = (IMG_UINT32 *) psMMUHeap->psMMUContext->pvPDCpuVAddr;
+       IMG_UINT32 ui32PDEntry;
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+#endif
+
+       
+       pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+       pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+       
+
+
+#if defined(PDUMP)
+       PDUMPCOMMENT("Page directory shared heap range copy");
+       PDUMPCOMMENT("  (Source heap MMU Context ID == %u, PT count == 0x%x)",
+                       psMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+                       psMMUHeap->ui32PageTableCount);
+       PDUMPCOMMENT("  (Destination MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+#endif 
+#ifdef SUPPORT_SGX_MMU_BYPASS
+       EnableHostAccess(psMMUContext);
+#endif
+
+       for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++)
+       {
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+               
+               PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
+#endif
+
+               
+               pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry];
+               if (pui32PDCpuVAddr[ui32PDEntry])
+               {
+
+               #if defined(PDUMP)
+
+               #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+                       if(psMMUContext->bPDumpActive)
+               #endif
+                       {
+                       PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+                       }
+               #endif
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+                       bInvalidateDirectoryCache = IMG_TRUE;
+#endif
+               }
+       }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+       DisableHostAccess(psMMUContext);
+#endif
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       if (bInvalidateDirectoryCache)
+       {
+               
+
+
+
+               MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
+       }
+#endif
+}
+
+
+static IMG_VOID
+MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
+                                                 IMG_DEV_VIRTADDR sDevVAddr,
+                                                 IMG_UINT32 ui32PageCount,
+                                                 IMG_HANDLE hUniqueTag)
+{
+       IMG_DEV_VIRTADDR        sTmpDevVAddr;
+       IMG_UINT32                      i;
+       IMG_UINT32                      ui32PDIndex;
+       IMG_UINT32                      ui32PTIndex;
+       IMG_UINT32                      *pui32Tmp;
+       IMG_BOOL                        bInvalidateDirectoryCache = IMG_FALSE;
+
+#if !defined (PDUMP)
+       PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+       
+       sTmpDevVAddr = sDevVAddr;
+
+       for(i=0; i<ui32PageCount; i++)
+       {
+               MMU_PT_INFO **ppsPTInfoList;
+
+               
+               ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+               
+               ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+               {
+                       
+                       ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+                       
+                       if (!ppsPTInfoList[0])
+                       {
+                               PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+
+                               
+                               sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+
+                               
+                               continue;
+                       }
+
+                       
+                       pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+                       
+                       if (!pui32Tmp)
+                       {
+                               continue;
+                       }
+
+                       CheckPT(ppsPTInfoList[0]);
+
+                       
+                       if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+                       {
+                               ppsPTInfoList[0]->ui32ValidPTECount--;
+                       }
+                       else
+                       {
+                               PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+                       }
+
+                       
+                       PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+                       
+                       pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+                                                                       | SGX_MMU_PTE_VALID;
+#else
+                       
+                       pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+                       CheckPT(ppsPTInfoList[0]);
+               }
+
+               
+
+               if (ppsPTInfoList[0] && ppsPTInfoList[0]->ui32ValidPTECount == 0)
+               {
+                       _DeferredFreePageTable(psMMUHeap, ui32PDIndex - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
+                       bInvalidateDirectoryCache = IMG_TRUE;
+               }
+
+               
+               sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+       }
+
+       if(bInvalidateDirectoryCache)
+       {
+               MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->psDevInfo);
+       }
+       else
+       {
+               MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+       }
+
+#if defined(PDUMP)
+       MMU_PDumpPageTables(psMMUHeap,
+                                               sDevVAddr,
+                                               psMMUHeap->ui32DataPageSize * ui32PageCount,
+                                               IMG_TRUE,
+                                               hUniqueTag);
+#endif 
+}
+
+
+static IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
+                                   IMG_SIZE_T ui32Start,
+                                   IMG_SIZE_T ui32End,
+                                   IMG_HANDLE hUniqueTag)
+{
+       MMU_HEAP *pMMUHeap = (MMU_HEAP*)pvMMUHeap;
+       IMG_DEV_VIRTADDR Start;
+
+       Start.uiAddr = ui32Start;
+
+       MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (ui32End - ui32Start) >> pMMUHeap->ui32PTShift, hUniqueTag);
+}
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+                       DEV_ARENA_DESCRIPTOR *psDevArena,
+                       RA_ARENA **ppsVMArena,
+                       PDUMP_MMU_ATTRIB **ppsMMUAttrib)
+{
+       MMU_HEAP *pMMUHeap;
+       IMG_UINT32 ui32ScaleSize;
+
+       PVR_UNREFERENCED_PARAMETER(ppsMMUAttrib);
+
+       PVR_ASSERT (psDevArena != IMG_NULL);
+
+       if (psDevArena == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid parameter"));
+               return IMG_NULL;
+       }
+
+       OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                sizeof (MMU_HEAP),
+                                (IMG_VOID **)&pMMUHeap, IMG_NULL,
+                                "MMU Heap");
+       if (pMMUHeap == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to OSAllocMem failed"));
+               return IMG_NULL;
+       }
+
+       pMMUHeap->psMMUContext = psMMUContext;
+       pMMUHeap->psDevArena = psDevArena;
+
+       
+
+
+       switch(pMMUHeap->psDevArena->ui32DataPageSize)
+       {
+               case 0x1000:
+                       ui32ScaleSize = 0;
+                       pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4K;
+                       break;
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+               case 0x4000:
+                       ui32ScaleSize = 2;
+                       pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_16K;
+                       break;
+               case 0x10000:
+                       ui32ScaleSize = 4;
+                       pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_64K;
+                       break;
+               case 0x40000:
+                       ui32ScaleSize = 6;
+                       pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_256K;
+                       break;
+               case 0x100000:
+                       ui32ScaleSize = 8;
+                       pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_1M;
+                       break;
+               case 0x400000:
+                       ui32ScaleSize = 10;
+                       pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M;
+                       break;
+#endif 
+               default:
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size"));
+                       goto ErrorFreeHeap;
+       }
+
+       
+       pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize;
+       pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize;
+       pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1;
+       
+       pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth;
+       pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize;
+       pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize);
+       pMMUHeap->ui32PTSize = (IMG_UINT32)(1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32);
+       
+       if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32))
+       {
+               pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32);
+       }
+       pMMUHeap->ui32PTECount = pMMUHeap->ui32PTSize >> 2;
+
+       
+       pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift;
+       pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth;
+       pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE));
+
+       
+
+
+/* External system cache violates this rule */
+#if !defined (SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+       if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask))
+       {
+               
+
+
+               PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr
+                                               & (pMMUHeap->ui32DataPageMask
+                                                       | pMMUHeap->ui32PTMask)) == 0);
+       }
+
+#endif
+       
+       pMMUHeap->ui32PTETotal = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift;
+
+       
+       pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift;
+
+       
+
+
+       pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotal + pMMUHeap->ui32PTECount - 1)
+                                                                               >> pMMUHeap->ui32PTBitWidth;
+
+       
+       pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
+                                                                       psDevArena->BaseDevVAddr.uiAddr,
+                                                                       psDevArena->ui32Size,
+                                                                       IMG_NULL,
+                                                                       MAX(HOST_PAGESIZE(), pMMUHeap->ui32DataPageSize),
+                                                                       IMG_NULL,
+                                                                       IMG_NULL,
+                                                                       &MMU_FreePageTables,
+                                                                       pMMUHeap);
+
+       if (pMMUHeap->psVMArena == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed"));
+               goto ErrorFreePagetables;
+       }
+
+#if defined(PDUMP)
+       
+       MMU_SetPDumpAttribs(&pMMUHeap->sMMUAttrib,
+                                               psMMUContext->psDeviceNode,
+                                               pMMUHeap->ui32DataPageMask,
+                                               pMMUHeap->ui32PTSize);
+       *ppsMMUAttrib = &pMMUHeap->sMMUAttrib;
+
+       PDUMPCOMMENT("Create MMU device from arena %s (Size == 0x%x, DataPageSize == 0x%x, BaseDevVAddr == 0x%x)",
+                       psDevArena->pszName,
+                       psDevArena->ui32Size,
+                       pMMUHeap->ui32DataPageSize,
+                       psDevArena->BaseDevVAddr.uiAddr);
+#endif 
+
+#if 0 
+       
+       if(psDevArena->ui32HeapID == SGX_TILED_HEAP_ID)
+       {
+               IMG_UINT32 ui32RegVal;
+               IMG_UINT32 ui32XTileStride;
+
+               
+
+
+
+
+               ui32XTileStride = 2;
+
+               ui32RegVal = (EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK
+                                               & ((psDevArena->BaseDevVAddr.uiAddr>>20)
+                                               << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT))
+                                       |(EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK
+                                               & (((psDevArena->BaseDevVAddr.uiAddr+psDevArena->ui32Size)>>20)
+                                               << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT))
+                                       |(EUR_CR_BIF_TILE0_CFG_MASK
+                                               & (((ui32XTileStride<<1)|8) << EUR_CR_BIF_TILE0_CFG_SHIFT));
+               PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_TILE0, ui32RegVal);
+       }
+#endif
+
+       
+
+       *ppsVMArena = pMMUHeap->psVMArena;
+
+       return pMMUHeap;
+
+       
+ErrorFreePagetables:
+       _DeferredFreePageTables (pMMUHeap);
+
+ErrorFreeHeap:
+       OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+       
+
+       return IMG_NULL;
+}
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap)
+{
+       if (pMMUHeap != IMG_NULL)
+       {
+               PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete"));
+
+               if(pMMUHeap->psVMArena)
+               {
+                       RA_Delete (pMMUHeap->psVMArena);
+               }
+
+#if defined(PDUMP)
+               PDUMPCOMMENT("Delete MMU device from arena %s (BaseDevVAddr == 0x%x, PT count for deferred free == 0x%x)",
+                               pMMUHeap->psDevArena->pszName,
+                               pMMUHeap->psDevArena->BaseDevVAddr.uiAddr,
+                               pMMUHeap->ui32PageTableCount);
+#endif 
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+               EnableHostAccess(pMMUHeap->psMMUContext);
+#endif
+               _DeferredFreePageTables (pMMUHeap);
+#ifdef SUPPORT_SGX_MMU_BYPASS
+               DisableHostAccess(pMMUHeap->psMMUContext);
+#endif
+
+               OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+               
+       }
+}
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+                  IMG_SIZE_T uSize,
+                  IMG_SIZE_T *pActualSize,
+                  IMG_UINT32 uFlags,
+                  IMG_UINT32 uDevVAddrAlignment,
+                  IMG_DEV_VIRTADDR *psDevVAddr)
+{
+       IMG_BOOL bStatus;
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+               "MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x",
+               uSize, uFlags, uDevVAddrAlignment));
+
+       
+
+       if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+       {
+               IMG_UINTPTR_T uiAddr;
+
+               bStatus = RA_Alloc (pMMUHeap->psVMArena,
+                                                       uSize,
+                                                       pActualSize,
+                                                       IMG_NULL,
+                                                       0,
+                                                       uDevVAddrAlignment,
+                                                       0,
+                                                       &uiAddr);
+               if(!bStatus)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: RA_Alloc of VMArena failed"));
+                       PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Alloc of DevVAddr failed from heap %s ID%d",
+                                                                       pMMUHeap->psDevArena->pszName,
+                                                                       pMMUHeap->psDevArena->ui32HeapID));
+                       return bStatus;
+               }
+
+               psDevVAddr->uiAddr = IMG_CAST_TO_DEVVADDR_UINT(uiAddr);
+       }
+
+       #ifdef SUPPORT_SGX_MMU_BYPASS
+       EnableHostAccess(pMMUHeap->psMMUContext);
+       #endif
+
+       
+       bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, uSize);
+
+       #ifdef SUPPORT_SGX_MMU_BYPASS
+       DisableHostAccess(pMMUHeap->psMMUContext);
+       #endif
+
+       if (!bStatus)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: _DeferredAllocPagetables failed"));
+               PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Failed to alloc pagetable(s) for DevVAddr 0x%8.8x from heap %s ID%d",
+                                                               psDevVAddr->uiAddr,
+                                                               pMMUHeap->psDevArena->pszName,
+                                                               pMMUHeap->psDevArena->ui32HeapID));
+               if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+               {
+                       
+                       RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE);
+               }
+       }
+
+       return bStatus;
+}
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+       PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+       if (pMMUHeap == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter"));
+               return;
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE, "MMU_Free: Freeing DevVAddr 0x%08X from heap %s ID%d",
+                                                               DevVAddr.uiAddr,
+                                                               pMMUHeap->psDevArena->pszName,
+                                                               pMMUHeap->psDevArena->ui32HeapID));
+
+       if((DevVAddr.uiAddr >= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr) &&
+               (DevVAddr.uiAddr + ui32Size <= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr + pMMUHeap->psDevArena->ui32Size))
+       {
+               RA_Free (pMMUHeap->psVMArena, DevVAddr.uiAddr, IMG_TRUE);
+               return;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,"MMU_Free: Couldn't free DevVAddr %08X from heap %s ID%d (not in range of heap))",
+                                                       DevVAddr.uiAddr,
+                                                       pMMUHeap->psDevArena->pszName,
+                                                       pMMUHeap->psDevArena->ui32HeapID));
+}
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMUHeap)
+{
+       PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+       
+}
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMUHeap)
+{
+       PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+       
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables    (MMU_HEAP *pMMUHeap,
+                                        IMG_DEV_VIRTADDR DevVAddr,
+                                        IMG_SIZE_T uSize,
+                                        IMG_BOOL bForUnmap,
+                                        IMG_HANDLE hUniqueTag)
+{
+       IMG_UINT32      ui32NumPTEntries;
+       IMG_UINT32      ui32PTIndex;
+       IMG_UINT32      *pui32PTEntry;
+
+       MMU_PT_INFO **ppsPTInfoList;
+       IMG_UINT32 ui32PDIndex;
+       IMG_UINT32 ui32PTDumpCount;
+
+       
+       ui32NumPTEntries = (uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift;
+
+       
+       ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+       
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+       
+       ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+       
+       PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
+
+       
+       while(ui32NumPTEntries > 0)
+       {
+               MMU_PT_INFO* psPTInfo = *ppsPTInfoList++;
+
+               if(ui32NumPTEntries <= pMMUHeap->ui32PTECount - ui32PTIndex)
+               {
+                       ui32PTDumpCount = ui32NumPTEntries;
+               }
+               else
+               {
+                       ui32PTDumpCount = pMMUHeap->ui32PTECount - ui32PTIndex;
+               }
+
+               if (psPTInfo)
+               {
+                       IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+                       ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+                       pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr;
+                       PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+               }
+
+               
+               ui32NumPTEntries -= ui32PTDumpCount;
+
+               
+               ui32PTIndex = 0;
+       }
+
+       PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : "");
+}
+#endif 
+
+
+static IMG_VOID
+MMU_MapPage (MMU_HEAP *pMMUHeap,
+                        IMG_DEV_VIRTADDR DevVAddr,
+                        IMG_DEV_PHYADDR DevPAddr,
+                        IMG_UINT32 ui32MemFlags)
+{
+       IMG_UINT32 ui32Index;
+       IMG_UINT32 *pui32Tmp;
+       IMG_UINT32 ui32MMUFlags = 0;
+       MMU_PT_INFO **ppsPTInfoList;
+
+       
+       PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+       
+
+       if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE))
+       {
+               
+               ui32MMUFlags = 0;
+       }
+       else if(PVRSRV_MEM_READ & ui32MemFlags)
+       {
+               
+               ui32MMUFlags |= SGX_MMU_PTE_READONLY;
+       }
+       else if(PVRSRV_MEM_WRITE & ui32MemFlags)
+       {
+               
+               ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
+       }
+
+       
+       if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
+       {
+               ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
+       }
+
+#if !defined(FIX_HW_BRN_25503)
+       
+       if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
+       {
+               ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
+       }
+#endif
+
+       
+
+
+       
+       ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+       
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+
+       CheckPT(ppsPTInfoList[0]);
+
+       
+       ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+       
+       pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+       {
+               IMG_UINT32 uTmp = pui32Tmp[ui32Index];
+               
+               
+               if (uTmp & SGX_MMU_PTE_VALID)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page is already valid for alloc at VAddr:0x%08X PDIdx:%u PTIdx:%u",
+                                                                       DevVAddr.uiAddr,
+                                                                       DevVAddr.uiAddr >> pMMUHeap->ui32PDShift,
+                                                                       ui32Index ));
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08X", uTmp));
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08X", DevPAddr.uiAddr));
+               }
+               
+               PVR_ASSERT((uTmp & SGX_MMU_PTE_VALID) == 0);
+       }
+#endif
+
+       
+       ppsPTInfoList[0]->ui32ValidPTECount++;
+
+       
+       pui32Tmp[ui32Index] = ((DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+                                               & ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT))
+                                               | SGX_MMU_PTE_VALID
+                                               | ui32MMUFlags;
+
+       CheckPT(ppsPTInfoList[0]);
+}
+
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+                               IMG_DEV_VIRTADDR DevVAddr,
+                               IMG_SYS_PHYADDR *psSysAddr,
+                               IMG_SIZE_T uSize,
+                               IMG_UINT32 ui32MemFlags,
+                               IMG_HANDLE hUniqueTag)
+{
+#if defined(PDUMP)
+       IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif 
+       IMG_UINT32 uCount, i;
+       IMG_DEV_PHYADDR DevPAddr;
+
+       PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+#if defined(PDUMP)
+       MapBaseDevVAddr = DevVAddr;
+#else
+       PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif 
+
+       for (i=0, uCount=0; uCount<uSize; i++, uCount+=pMMUHeap->ui32DataPageSize)
+       {
+               IMG_SYS_PHYADDR sSysAddr;
+
+               sSysAddr = psSysAddr[i];
+
+
+               
+               PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+               DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
+
+               MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+               DevVAddr.uiAddr += pMMUHeap->ui32DataPageSize;
+
+               PVR_DPF ((PVR_DBG_MESSAGE,
+                                "MMU_MapScatter: devVAddr=%08X, SysAddr=%08X, size=0x%x/0x%x",
+                                 DevVAddr.uiAddr, sSysAddr.uiAddr, uCount, uSize));
+       }
+
+#if defined(PDUMP)
+       MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif 
+}
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+                         IMG_DEV_VIRTADDR DevVAddr,
+                         IMG_SYS_PHYADDR SysPAddr,
+                         IMG_SIZE_T uSize,
+                         IMG_UINT32 ui32MemFlags,
+                         IMG_HANDLE hUniqueTag)
+{
+       IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+       IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif 
+       IMG_UINT32 uCount;
+       IMG_UINT32 ui32VAdvance;
+       IMG_UINT32 ui32PAdvance;
+
+       PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+       PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPages: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=%08X, size=0x%x",
+                                                               pMMUHeap->psDevArena->pszName,
+                                                               pMMUHeap->psDevArena->ui32HeapID,
+                                                               DevVAddr.uiAddr, 
+                                                               SysPAddr.uiAddr,
+                                                               uSize));
+
+       
+       ui32VAdvance = pMMUHeap->ui32DataPageSize;
+       ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+       MapBaseDevVAddr = DevVAddr;
+#else
+       PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif 
+
+       DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+       
+       PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+#if defined(FIX_HW_BRN_23281)
+       if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+       {
+               ui32VAdvance *= 2;
+       }
+#endif
+
+       
+
+
+       if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+       {
+               ui32PAdvance = 0;
+       }
+
+       for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+       {
+               MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+               DevVAddr.uiAddr += ui32VAdvance;
+               DevPAddr.uiAddr += ui32PAdvance;
+       }
+
+#if defined(PDUMP)
+       MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif 
+}
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP          *pMMUHeap,
+                          IMG_DEV_VIRTADDR   MapBaseDevVAddr,
+                          IMG_SIZE_T         uByteSize,
+                          IMG_CPU_VIRTADDR   CpuVAddr,
+                          IMG_HANDLE         hOSMemHandle,
+                          IMG_DEV_VIRTADDR  *pDevVAddr,
+                          IMG_UINT32         ui32MemFlags,
+                          IMG_HANDLE         hUniqueTag)
+{
+       IMG_UINT32                      i;
+       IMG_UINT32                      uOffset = 0;
+       IMG_DEV_VIRTADDR        MapDevVAddr;
+       IMG_UINT32                      ui32VAdvance;
+       IMG_UINT32                      ui32PAdvance;
+
+#if !defined (PDUMP)
+       PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+       PVR_DPF ((PVR_DBG_MESSAGE,
+                       "MMU_MapShadow: DevVAddr:%08X, Bytes:0x%x, CPUVAddr:%08X",
+                       MapBaseDevVAddr.uiAddr,
+                       uByteSize,
+                       (IMG_UINTPTR_T)CpuVAddr));
+
+       
+       ui32VAdvance = pMMUHeap->ui32DataPageSize;
+       ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+       
+       PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+       PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0);
+       pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+#if defined(FIX_HW_BRN_23281)
+       if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+       {
+               ui32VAdvance *= 2;
+       }
+#endif
+
+       
+
+
+       if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+       {
+               ui32PAdvance = 0;
+       }
+
+       
+       MapDevVAddr = MapBaseDevVAddr;
+       for (i=0; i<uByteSize; i+=ui32VAdvance)
+       {
+               IMG_CPU_PHYADDR CpuPAddr;
+               IMG_DEV_PHYADDR DevPAddr;
+
+               if(CpuVAddr)
+               {
+                       CpuPAddr = OSMapLinToCPUPhys (hOSMemHandle,
+                                                                                 (IMG_VOID *)((IMG_UINTPTR_T)CpuVAddr + uOffset));
+               }
+               else
+               {
+                       CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+               }
+               DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+               
+               PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+               PVR_DPF ((PVR_DBG_MESSAGE,
+                               "Offset=0x%x: CpuVAddr=%08X, CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X",
+                               uOffset,
+                               (IMG_UINTPTR_T)CpuVAddr + uOffset,
+                               CpuPAddr.uiAddr,
+                               MapDevVAddr.uiAddr,
+                               DevPAddr.uiAddr));
+
+               MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+
+               
+               MapDevVAddr.uiAddr += ui32VAdvance;
+               uOffset += ui32PAdvance;
+       }
+
+#if defined(PDUMP)
+       MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag);
+#endif 
+}
+
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+                               IMG_DEV_VIRTADDR sDevVAddr,
+                               IMG_UINT32 ui32PageCount,
+                               IMG_HANDLE hUniqueTag)
+{
+       IMG_UINT32                      uPageSize = psMMUHeap->ui32DataPageSize;
+       IMG_DEV_VIRTADDR        sTmpDevVAddr;
+       IMG_UINT32                      i;
+       IMG_UINT32                      ui32PDIndex;
+       IMG_UINT32                      ui32PTIndex;
+       IMG_UINT32                      *pui32Tmp;
+
+#if !defined (PDUMP)
+       PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+       
+       sTmpDevVAddr = sDevVAddr;
+
+       for(i=0; i<ui32PageCount; i++)
+       {
+               MMU_PT_INFO **ppsPTInfoList;
+
+               
+               ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+               
+               ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+               
+               ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+               
+               if (!ppsPTInfoList[0])
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
+                                                                       sTmpDevVAddr.uiAddr,
+                                                                       sDevVAddr.uiAddr,
+                                                                       i,
+                                                                       ui32PDIndex,
+                                                                       ui32PTIndex));
+
+                       
+                       sTmpDevVAddr.uiAddr += uPageSize;
+
+                       
+                       continue;
+               }
+
+               CheckPT(ppsPTInfoList[0]);
+
+               
+               pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+               
+               if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+               {
+                       ppsPTInfoList[0]->ui32ValidPTECount--;
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
+                                                                       sTmpDevVAddr.uiAddr,
+                                                                       sDevVAddr.uiAddr,
+                                                                       i,
+                                                                       ui32PDIndex,
+                                                                       ui32PTIndex));
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08X", pui32Tmp[ui32PTIndex]));
+               }
+
+               
+               PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+               
+               pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+                                                               | SGX_MMU_PTE_VALID;
+#else
+               
+               pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+               CheckPT(ppsPTInfoList[0]);
+
+               
+               sTmpDevVAddr.uiAddr += uPageSize;
+       }
+
+       MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+
+#if defined(PDUMP)
+       MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag);
+#endif 
+}
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
+{
+       IMG_UINT32 *pui32PageTable;
+       IMG_UINT32 ui32Index;
+       IMG_DEV_PHYADDR sDevPAddr;
+       MMU_PT_INFO **ppsPTInfoList;
+
+       
+       ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+       
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+       if (!ppsPTInfoList[0])
+       {
+               PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+               sDevPAddr.uiAddr = 0;
+               return sDevPAddr;
+       }
+
+       
+       ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+       
+       pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+       
+       sDevPAddr.uiAddr = pui32PageTable[ui32Index];
+
+       
+       sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+
+       
+       sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+       return sDevPAddr;
+}
+
+
+IMG_DEV_PHYADDR MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext)
+{
+       return (pMMUContext->sPDDevPAddr);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
+                                                                  IMG_DEV_VIRTADDR sDevVAddr,
+                                                                  IMG_DEV_PHYADDR *pDevPAddr,
+                                                                  IMG_CPU_PHYADDR *pCpuPAddr)
+{
+       MMU_HEAP *pMMUHeap;
+       IMG_DEV_PHYADDR DevPAddr;
+
+       
+
+       pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap);
+
+       DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
+       pCpuPAddr->uiAddr = DevPAddr.uiAddr; 
+       pDevPAddr->uiAddr = DevPAddr.uiAddr;
+
+       return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE              hDevCookie,
+                                                               IMG_HANDLE              hDevMemContext,
+                                                               IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+       if (!hDevCookie || !hDevMemContext || !psPDDevPAddr)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       *psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       RA_ARENA *psLocalDevMemArena;
+       IMG_HANDLE hOSMemHandle = IMG_NULL;
+       IMG_BYTE *pui8MemBlock = IMG_NULL;
+       IMG_SYS_PHYADDR sMemBlockSysPAddr;
+       IMG_CPU_PHYADDR sMemBlockCpuPAddr;
+
+       SysAcquireData(&psSysData);
+
+       psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+       
+       if(psLocalDevMemArena == IMG_NULL)
+       {
+               
+               eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                     3 * SGX_MMU_PAGE_SIZE,
+                                                     SGX_MMU_PAGE_SIZE,
+                                                     (IMG_VOID **)&pui8MemBlock,
+                                                     &hOSMemHandle);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to OSAllocPages failed"));
+                       return eError;
+               }
+
+               
+               if(pui8MemBlock)
+               {
+                       sMemBlockCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle,
+                                                                                                 pui8MemBlock);
+               }
+               else
+               {
+                       
+                       sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0);
+               }
+       }
+       else
+       {
+               
+
+               if(RA_Alloc(psLocalDevMemArena,
+                                       3 * SGX_MMU_PAGE_SIZE,
+                                       IMG_NULL,
+                                       IMG_NULL,
+                                       0,
+                                       SGX_MMU_PAGE_SIZE,
+                                       0,
+                                       &(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed"));
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+
+               
+               sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
+               pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr,
+                                                                         SGX_MMU_PAGE_SIZE * 3,
+                                                                         PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                                         &hOSMemHandle);
+               if(!pui8MemBlock)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR failed to map page tables"));
+                       return PVRSRV_ERROR_BAD_MAPPING;
+               }
+       }
+
+       psDevInfo->hBIFResetPDOSMemHandle = hOSMemHandle;
+       psDevInfo->sBIFResetPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr);
+       psDevInfo->sBIFResetPTDevPAddr.uiAddr = psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+       psDevInfo->sBIFResetPageDevPAddr.uiAddr = psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+       
+       
+       psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock;
+       psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE);
+
+       
+       OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
+       OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
+       
+       OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE);
+
+       return PVRSRV_OK;
+}
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+       SYS_DATA *psSysData;
+       RA_ARENA *psLocalDevMemArena;
+       IMG_SYS_PHYADDR sPDSysPAddr;
+
+       SysAcquireData(&psSysData);
+
+       psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+       
+       if(psLocalDevMemArena == IMG_NULL)
+       {
+               OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                       3 * SGX_MMU_PAGE_SIZE,
+                                       psDevInfo->pui32BIFResetPD,
+                                       psDevInfo->hBIFResetPDOSMemHandle);
+       }
+       else
+       {
+               OSUnMapPhysToLin(psDevInfo->pui32BIFResetPD,
+                         3 * SGX_MMU_PAGE_SIZE,
+                         PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                         psDevInfo->hBIFResetPDOSMemHandle);
+
+               sPDSysPAddr = SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->sBIFResetPDDevPAddr);
+               RA_Free(psLocalDevMemArena, sPDSysPAddr.uiAddr, IMG_FALSE);
+       }
+}
+
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE        *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       RA_ARENA *psLocalDevMemArena;
+       IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
+       IMG_HANDLE hPDPageOSMemHandle = IMG_NULL;
+       IMG_UINT32 *pui32PD = IMG_NULL;
+       IMG_UINT32 *pui32PT = IMG_NULL;
+       IMG_CPU_PHYADDR sCpuPAddr;
+       IMG_DEV_PHYADDR sPTDevPAddr;
+       IMG_DEV_PHYADDR sPDDevPAddr;
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+       IMG_UINT32 ui32PDOffset;
+       IMG_UINT32 ui32PTOffset;
+
+       psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+       SysAcquireData(&psSysData);
+
+       psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+       
+       if(psLocalDevMemArena == IMG_NULL)
+       {
+               
+               eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                  SGX_MMU_PAGE_SIZE,
+                                                  SGX_MMU_PAGE_SIZE,
+                                                  (IMG_VOID **)&pui32PT,
+                                                  &hPTPageOSMemHandle);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+                       return eError;
+               }
+               ui32PTOffset = 0;
+
+               eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                  SGX_MMU_PAGE_SIZE,
+                                                  SGX_MMU_PAGE_SIZE,
+                                                  (IMG_VOID **)&pui32PD,
+                                                  &hPDPageOSMemHandle);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+                       return eError;
+               }
+               ui32PDOffset = 0;
+
+               
+               if(pui32PT)
+        {
+            sCpuPAddr = OSMapLinToCPUPhys(hPTPageOSMemHandle,
+                                                                                 pui32PT);
+        }
+        else
+        {
+            
+            sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
+        }
+               sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+               if(pui32PD)
+        {
+            sCpuPAddr = OSMapLinToCPUPhys(hPDPageOSMemHandle,
+                                                                                 pui32PD);
+        }
+        else
+        {
+            
+            sCpuPAddr = OSMemHandleToCpuPAddr(hPDPageOSMemHandle, 0);
+        }
+               sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+       }
+       else
+       {
+               
+
+               if(RA_Alloc(psLocalDevMemArena,
+                                       SGX_MMU_PAGE_SIZE * 2,
+                                       IMG_NULL,
+                                       IMG_NULL,
+                                       0,
+                                       SGX_MMU_PAGE_SIZE,
+                                       0,
+                                       &(psDevInfo->sBRN22997SysPAddr.uiAddr))!= IMG_TRUE)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to RA_Alloc failed"));
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+
+               
+               sCpuPAddr = SysSysPAddrToCpuPAddr(psDevInfo->sBRN22997SysPAddr);
+               pui32PT = OSMapPhysToLin(sCpuPAddr,
+                                                               SGX_MMU_PAGE_SIZE * 2,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                                               &hPTPageOSMemHandle);
+               if(!pui32PT)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR failed to map page tables"));
+                       return PVRSRV_ERROR_BAD_MAPPING;
+               }
+               ui32PTOffset = 0;
+
+               
+               sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+               
+               pui32PD = pui32PT + SGX_MMU_PAGE_SIZE/sizeof(IMG_UINT32);
+               ui32PDOffset = SGX_MMU_PAGE_SIZE;
+               hPDPageOSMemHandle = hPTPageOSMemHandle;
+               sPDDevPAddr.uiAddr = sPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+       }
+
+       OSMemSet(pui32PD, 0, SGX_MMU_PAGE_SIZE);
+       OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
+
+       
+       PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDPageOSMemHandle, ui32PDOffset, pui32PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+       PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPTPageOSMemHandle, ui32PTOffset, pui32PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+       PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+       PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+       psDevInfo->hBRN22997PTPageOSMemHandle = hPTPageOSMemHandle;
+       psDevInfo->hBRN22997PDPageOSMemHandle = hPDPageOSMemHandle;
+       psDevInfo->sBRN22997PTDevPAddr = sPTDevPAddr;
+       psDevInfo->sBRN22997PDDevPAddr = sPDDevPAddr;
+       psDevInfo->pui32BRN22997PD = pui32PD;
+       psDevInfo->pui32BRN22997PT = pui32PT;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+       IMG_UINT32 *pui32PD = psDevInfo->pui32BRN22997PD;
+       IMG_UINT32 *pui32PT = psDevInfo->pui32BRN22997PT;
+       IMG_UINT32 ui32PDIndex;
+       IMG_UINT32 ui32PTIndex;
+       IMG_DEV_VIRTADDR sDevVAddr;
+       volatile IMG_UINT32 *pui32HostPort;
+       IMG_UINT32 ui32BIFCtrl;
+
+       
+       
+       
+       pui32HostPort = (volatile IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvHostPortBaseKM) + SYS_SGX_HOSTPORT_BRN23030_OFFSET);
+
+       
+       sDevVAddr.uiAddr = SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET;
+
+       ui32PDIndex = (sDevVAddr.uiAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+       ui32PTIndex = (sDevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+       
+       pui32PD[ui32PDIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+                                                       | SGX_MMU_PDE_VALID;
+       
+       pui32PT[ui32PTIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+                                                       | SGX_MMU_PTE_VALID;
+
+       PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+       PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+       
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
+                                psDevInfo->sBRN22997PDDevPAddr.uiAddr);
+       PDUMPPDREG(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sBRN22997PDDevPAddr.uiAddr, PDUMP_PD_UNIQUETAG);
+
+       
+       ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+       PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+       PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+
+       
+       if (pui32HostPort)
+       {
+                
+               IMG_UINT32 ui32Tmp;
+               ui32Tmp = *pui32HostPort;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR,"Host Port not present for BRN22997 workaround"));
+       }
+
+       
+
+
+
+
+       
+       PDUMPCOMMENT("RDW :SGXMEM:v4:%08X\r\n", sDevVAddr.uiAddr);
+       
+    PDUMPCOMMENT("SAB :SGXMEM:v4:%08X 4 0 hostport.bin", sDevVAddr.uiAddr);
+
+       
+       pui32PD[ui32PDIndex] = 0;
+       pui32PT[ui32PTIndex] = 0;
+
+       
+       PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+       PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+       PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+       PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+}
+
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       SYS_DATA *psSysData;
+       RA_ARENA *psLocalDevMemArena;
+       PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+
+       SysAcquireData(&psSysData);
+
+       psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+       PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PDPageOSMemHandle, psDevInfo->pui32BRN22997PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+       PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PTPageOSMemHandle, psDevInfo->pui32BRN22997PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+       
+       if(psLocalDevMemArena == IMG_NULL)
+       {
+               if (psDevInfo->pui32BRN22997PD != IMG_NULL)
+               {
+                       OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                 SGX_MMU_PAGE_SIZE,
+                                                 psDevInfo->pui32BRN22997PD,
+                                                 psDevInfo->hBRN22997PDPageOSMemHandle);
+               }
+
+               if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+               {
+                       OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+                                                 SGX_MMU_PAGE_SIZE,
+                                                 psDevInfo->pui32BRN22997PT,
+                                                 psDevInfo->hBRN22997PTPageOSMemHandle);
+               }
+       }
+       else
+       {
+               if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+               {
+                       OSUnMapPhysToLin(psDevInfo->pui32BRN22997PT,
+                                SGX_MMU_PAGE_SIZE * 2,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                                psDevInfo->hBRN22997PTPageOSMemHandle);
+
+
+                       RA_Free(psLocalDevMemArena, psDevInfo->sBRN22997SysPAddr.uiAddr, IMG_FALSE);
+               }
+       }
+}
+#endif 
+
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+   IMG_UINT32 *pui32PT;
+   PVRSRV_SGXDEV_INFO *psDevInfo;
+       IMG_UINT32 ui32PDIndex;
+       IMG_UINT32 ui32PTIndex;
+#if defined(PDUMP)
+   PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+
+       psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+#if defined(PDUMP)
+    sMMUAttrib = psDevInfo->sMMUAttrib;
+    MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+                        SGX_MMU_PAGE_MASK,
+                        SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+#if defined(PDUMP)
+       {
+        IMG_CHAR szScript[128];
+        sprintf(szScript, "MALLOC :EXTSYSCACHE:PA_%08X%08X %u %u 0x%08X\r\n", 0, psDevInfo->sExtSysCacheRegsDevPBase.uiAddr, SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE, psDevInfo->sExtSysCacheRegsDevPBase.uiAddr);
+        PDumpOSWriteString2(szScript, PDUMP_FLAGS_CONTINUOUS);
+       }
+#endif
+
+
+       ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+       ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+       
+   pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+
+       pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+                                                       | SGX_MMU_PTE_VALID;
+
+       
+#if defined(PDUMP)
+    /* Add the entery to the PT */
+    {
+        IMG_DEV_PHYADDR sDevPAddr;
+        IMG_CPU_PHYADDR sCpuPAddr;
+        IMG_UINT32 ui32PageMask;
+        IMG_UINT32 ui32PTE;
+        PVRSRV_ERROR eErr;
+
+        PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+        ui32PageMask = sMMUAttrib.ui32PTSize - 1;
+        sCpuPAddr = OSMapLinToCPUPhys(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->hPTPageOSMemHandle, &pui32PT[ui32PTIndex]);
+        sDevPAddr = SysCpuPAddrToDevPAddr(sMMUAttrib.sDevId.eDeviceType, sCpuPAddr);
+        ui32PTE = *((IMG_UINT32 *) (&pui32PT[ui32PTIndex]));
+
+        eErr = PDumpOSBufprintf(hScript,
+                                ui32MaxLenScript,
+                                "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+                                sMMUAttrib.sDevId.pszPDumpDevName,
+                                (IMG_UINT32)(IMG_UINTPTR_T)PDUMP_PT_UNIQUETAG,
+                                (sDevPAddr.uiAddr) & ~ui32PageMask,
+                                (sDevPAddr.uiAddr) & ui32PageMask,
+                                "EXTSYSCACHE",
+                                (IMG_UINT32)(IMG_UINTPTR_T)PDUMP_PD_UNIQUETAG,
+                                (ui32PTE & sMMUAttrib.ui32PDEMask) << sMMUAttrib.ui32PTEAlignShift,
+                                ui32PTE & ~sMMUAttrib.ui32PDEMask);
+        if(eErr != PVRSRV_OK)
+        {
+            return eErr;
+        }
+        PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+    }
+#endif
+
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       SYS_DATA *psSysData;
+       RA_ARENA *psLocalDevMemArena;
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+       IMG_UINT32 ui32PDIndex;
+       IMG_UINT32 ui32PTIndex;
+       IMG_UINT32 *pui32PT;
+#if defined(PDUMP)
+       PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+
+       psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+#if defined(PDUMP)
+   sMMUAttrib = psDevInfo->sMMUAttrib;
+    MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+                        SGX_MMU_PAGE_MASK,
+                        SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+       SysAcquireData(&psSysData);
+
+       psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+       
+       ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+       ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+    /* Only unmap it if the PT hasn't already been freed */
+    if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex])
+       {
+        if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+               {
+
+            pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+            pui32PT[ui32PTIndex] = 0;
+            PDUMPMEMPTENTRIES(&sMMUAttrib, psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->hPDOSMemHandle, &pui32PT[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+        }
+       }
+
+       return PVRSRV_OK;
+}
+#endif
+
+
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
+{
+       volatile IMG_UINT32 ui32WriteData;
+       volatile IMG_UINT32 ui32ReadData;
+       volatile IMG_UINT32 *pMem32 = (volatile IMG_UINT32 *)pMem;
+       IMG_INT n;
+       IMG_BOOL bOK=IMG_TRUE;
+
+       ui32WriteData = 0xffffffff;
+
+       for (n=0; n<1024; n++)
+       {
+               pMem32[n] = ui32WriteData;
+               ui32ReadData = pMem32[n];
+
+               if (ui32WriteData != ui32ReadData)
+               {
+                       
+                       PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+                       PVR_DBG_BREAK;
+                       bOK = IMG_FALSE;
+               }
+       }
+
+       ui32WriteData = 0;
+
+       for (n=0; n<1024; n++)
+       {
+               pMem32[n] = ui32WriteData;
+               ui32ReadData = pMem32[n];
+
+               if (ui32WriteData != ui32ReadData)
+               {
+                       
+                       PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+                       PVR_DBG_BREAK;
+                       bOK = IMG_FALSE;
+               }
+       }
+
+       if (bOK)
+       {
+               PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X is OK", sDevPAddr.uiAddr));
+       }
+       else
+       {
+               PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X *** FAILED ***", sDevPAddr.uiAddr));
+       }
+}
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/mmu.h b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/mmu.h
new file mode 100644 (file)
index 0000000..e92b4e0
--- /dev/null
@@ -0,0 +1,146 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _MMU_H_
+#define _MMU_H_
+
+#include "sgxinfokm.h"
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap);
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+                       DEV_ARENA_DESCRIPTOR *psDevArena,
+                       RA_ARENA **ppsVMArena,
+                       PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap);
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+           IMG_SIZE_T uSize,
+           IMG_SIZE_T *pActualSize,
+           IMG_UINT32 uFlags,
+                  IMG_UINT32 uDevVAddrAlignment,
+           IMG_DEV_VIRTADDR *pDevVAddr);
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap,
+          IMG_DEV_VIRTADDR DevVAddr,
+                 IMG_UINT32 ui32Size);
+
+IMG_VOID 
+MMU_Enable (MMU_HEAP *pMMUHeap);
+
+IMG_VOID 
+MMU_Disable (MMU_HEAP *pMMUHeap);
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+                         IMG_DEV_VIRTADDR DevVAddr,
+                         IMG_SYS_PHYADDR SysPAddr,
+                         IMG_SIZE_T uSize,
+                         IMG_UINT32 ui32MemFlags,
+                         IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP          * pMMUHeap,
+               IMG_DEV_VIRTADDR    MapBaseDevVAddr,
+               IMG_SIZE_T          uByteSize, 
+               IMG_CPU_VIRTADDR    CpuVAddr,
+               IMG_HANDLE          hOSMemHandle,
+               IMG_DEV_VIRTADDR  * pDevVAddr,
+               IMG_UINT32          ui32MemFlags,
+               IMG_HANDLE          hUniqueTag);
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+             IMG_DEV_VIRTADDR sDevVAddr,
+             IMG_UINT32 ui32PageCount,
+             IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+                               IMG_DEV_VIRTADDR DevVAddr,
+                               IMG_SYS_PHYADDR *psSysAddr,
+                               IMG_SIZE_T uSize,
+                               IMG_UINT32 ui32MemFlags,
+                               IMG_HANDLE hUniqueTag);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext);
+
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext);
+#endif
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE        *psDeviceNode);
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif 
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif 
+
+IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMU_Heap);
+
+#if defined(PDUMP)
+IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext);
+#endif 
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/pb.c b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/pb.c
new file mode 100644 (file)
index 0000000..71d47af
--- /dev/null
@@ -0,0 +1,459 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "sgx_bridge_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "sgxutils.h"
+
+#ifndef __linux__
+#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#endif
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_INSERT(PVRSRV_STUB_PBDESC)
+static IMPLEMENT_LIST_REMOVE(PVRSRV_STUB_PBDESC)
+
+static PRESMAN_ITEM psResItemCreateSharedPB = IMG_NULL;
+static PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB = IMG_NULL;
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+
+IMG_EXPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA  *psPerProc,
+                                         IMG_HANDLE                            hDevCookie,
+                                         IMG_BOOL                              bLockOnFailure,
+                                         IMG_UINT32                            ui32TotalPBSize,
+                                         IMG_HANDLE                            *phSharedPBDesc,
+                                         PVRSRV_KERNEL_MEM_INFO        **ppsSharedPBDescKernelMemInfo,
+                                         PVRSRV_KERNEL_MEM_INFO        **ppsHWPBDescKernelMemInfo,
+                                         PVRSRV_KERNEL_MEM_INFO        **ppsBlockKernelMemInfo,
+                                         PVRSRV_KERNEL_MEM_INFO        **ppsHWBlockKernelMemInfo,
+                                         PVRSRV_KERNEL_MEM_INFO        ***pppsSharedPBDescSubKernelMemInfos,
+                                         IMG_UINT32                            *ui32SharedPBDescSubKernelMemInfosCount)
+{
+       PVRSRV_STUB_PBDESC *psStubPBDesc;
+       PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL;
+       PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+       PVRSRV_ERROR eError;
+
+       psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+       psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+       if (psStubPBDesc != IMG_NULL)
+       {
+               IMG_UINT32 i;
+               PRESMAN_ITEM psResItem;
+
+               if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                       "SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+                                       ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+               }
+
+               if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                         sizeof(PVRSRV_KERNEL_MEM_INFO *)
+                                               * psStubPBDesc->ui32SubKernelMemInfosCount,
+                                         (IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos,
+                                         IMG_NULL,
+                                         "Array of Kernel Memory Info") != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed"));
+
+                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                       goto ExitNotFound;
+               }
+
+               psResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                         RESMAN_TYPE_SHARED_PB_DESC,
+                                                                         psStubPBDesc,
+                                                                         0,
+                                                                         &SGXCleanupSharedPBDescCallback);
+
+               if (psResItem == IMG_NULL)
+               {
+                       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                         sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
+                                         ppsSharedPBDescSubKernelMemInfos,
+                                         0);
+
+
+                       PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+                       eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+                       goto ExitNotFound;
+               }
+
+               *ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo;
+               *ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo;
+               *ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo;
+               *ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo;
+
+               *ui32SharedPBDescSubKernelMemInfosCount =
+                       psStubPBDesc->ui32SubKernelMemInfosCount;
+
+               *pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos;
+
+               for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++)
+               {
+                       ppsSharedPBDescSubKernelMemInfos[i] =
+                               psStubPBDesc->ppsSubKernelMemInfos[i];
+               }
+
+               psStubPBDesc->ui32RefCount++;
+               *phSharedPBDesc = (IMG_HANDLE)psResItem;
+               return PVRSRV_OK;
+       }
+
+       eError = PVRSRV_OK;
+       if (bLockOnFailure)
+       {
+               if (psResItemCreateSharedPB == IMG_NULL)
+               {
+                       psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext,
+                                 RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+                                 psPerProc,
+                                 0,
+                                 &SGXCleanupSharedPBDescCreateLockCallback);
+
+                       if (psResItemCreateSharedPB == IMG_NULL)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+                               eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+                               goto ExitNotFound;
+                       }
+                       PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+                       psPerProcCreateSharedPB = psPerProc;
+               }
+               else
+               {
+                        eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
+               }
+       }
+ExitNotFound:
+       *phSharedPBDesc = IMG_NULL;
+
+       return eError;
+}
+
+
+static PVRSRV_ERROR
+SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
+{
+
+       IMG_UINT32 i;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
+
+
+
+
+       psStubPBDescIn->ui32RefCount--;
+       if (psStubPBDescIn->ui32RefCount == 0)
+       {
+               List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
+               for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
+               {
+
+                       PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
+                                                                 psStubPBDescIn->ppsSubKernelMemInfos[i]);
+               }
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDescIn->ui32SubKernelMemInfosCount,
+                                 psStubPBDescIn->ppsSubKernelMemInfos,
+                                 0);
+               psStubPBDescIn->ppsSubKernelMemInfos = IMG_NULL;
+
+               PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psBlockKernelMemInfo);
+
+               PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWBlockKernelMemInfo);
+
+               PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWPBDescKernelMemInfo);
+
+               PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psSharedPBDescKernelMemInfo);
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_STUB_PBDESC),
+                                 psStubPBDescIn,
+                                 0);
+
+
+
+               SGXCleanupRequest(psDeviceNode,
+                                                 IMG_NULL,
+                                                 PVRSRV_CLEANUPCMD_PB);
+       }
+       return PVRSRV_OK;
+
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+       PVRSRV_STUB_PBDESC *psStubPBDesc = (PVRSRV_STUB_PBDESC *)pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       return SGXCleanupSharedPBDescKM(psStubPBDesc);
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+#ifdef DEBUG
+       PVRSRV_PER_PROCESS_DATA *psPerProc = (PVRSRV_PER_PROCESS_DATA *)pvParam;
+       PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
+#else
+       PVR_UNREFERENCED_PARAMETER(pvParam);
+#endif
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       psPerProcCreateSharedPB = IMG_NULL;
+       psResItemCreateSharedPB = IMG_NULL;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc)
+{
+       PVR_ASSERT(hSharedPBDesc != IMG_NULL);
+
+       return ResManFreeResByPtr(hSharedPBDesc);
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA   *psPerProc,
+                                        IMG_HANDLE                                     hDevCookie,
+                                        PVRSRV_KERNEL_MEM_INFO         *psSharedPBDescKernelMemInfo,
+                                        PVRSRV_KERNEL_MEM_INFO         *psHWPBDescKernelMemInfo,
+                                        PVRSRV_KERNEL_MEM_INFO         *psBlockKernelMemInfo,
+                                        PVRSRV_KERNEL_MEM_INFO         *psHWBlockKernelMemInfo,
+                                        IMG_UINT32                                     ui32TotalPBSize,
+                                        IMG_HANDLE                                     *phSharedPBDesc,
+                                        PVRSRV_KERNEL_MEM_INFO         **ppsSharedPBDescSubKernelMemInfos,
+                                        IMG_UINT32                                     ui32SharedPBDescSubKernelMemInfosCount)
+{
+       PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL;
+       PVRSRV_ERROR eRet = PVRSRV_ERROR_INVALID_PERPROC;
+       IMG_UINT32 i;
+       PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+       PRESMAN_ITEM psResItem;
+
+
+       if (psPerProcCreateSharedPB != psPerProc)
+       {
+               goto NoAdd;
+       }
+       else
+       {
+               PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL);
+
+               ResManFreeResByPtr(psResItemCreateSharedPB);
+
+               PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL);
+               PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+       }
+
+       psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+       psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+       if (psStubPBDesc != IMG_NULL)
+       {
+               if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                       "SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+                                       ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+
+               }
+
+
+               psResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                         RESMAN_TYPE_SHARED_PB_DESC,
+                                                                         psStubPBDesc,
+                                                                         0,
+                                                                         &SGXCleanupSharedPBDescCallback);
+               if (psResItem == IMG_NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "SGXAddSharedPBDescKM: "
+                               "Failed to register existing shared "
+                               "PBDesc with the resource manager"));
+                       goto NoAddKeepPB;
+               }
+
+
+               psStubPBDesc->ui32RefCount++;
+
+               *phSharedPBDesc = (IMG_HANDLE)psResItem;
+               eRet = PVRSRV_OK;
+               goto NoAddKeepPB;
+       }
+
+       if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_STUB_PBDESC),
+                                 (IMG_VOID **)&psStubPBDesc,
+                                 0,
+                                 "Stub Parameter Buffer Description") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
+                                       "StubPBDesc"));
+               eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto NoAdd;
+       }
+
+
+       psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+
+       if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_KERNEL_MEM_INFO *)
+                                 * ui32SharedPBDescSubKernelMemInfosCount,
+                                 (IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos,
+                                 0,
+                                 "Array of Kernel Memory Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+                                "Failed to alloc "
+                                "StubPBDesc->ppsSubKernelMemInfos"));
+               eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto NoAdd;
+       }
+
+       if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
+          != PVRSRV_OK)
+       {
+               goto NoAdd;
+       }
+
+       if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
+          != PVRSRV_OK)
+       {
+               goto NoAdd;
+       }
+
+       if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
+          != PVRSRV_OK)
+       {
+               goto NoAdd;
+       }
+
+       if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo)
+          != PVRSRV_OK)
+       {
+               goto NoAdd;
+       }
+
+       psStubPBDesc->ui32RefCount = 1;
+       psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
+       psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
+       psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
+       psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
+       psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo;
+
+       psStubPBDesc->ui32SubKernelMemInfosCount =
+               ui32SharedPBDescSubKernelMemInfosCount;
+       for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+       {
+               psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i];
+               if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i])
+                  != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+                                        "Failed to dissociate shared PBDesc "
+                                        "from process"));
+                       goto NoAdd;
+               }
+       }
+
+       psResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                 RESMAN_TYPE_SHARED_PB_DESC,
+                                                                 psStubPBDesc,
+                                                                 0,
+                                                                 &SGXCleanupSharedPBDescCallback);
+       if (psResItem == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+                                        "Failed to register shared PBDesc "
+                                        " with the resource manager"));
+               goto NoAdd;
+       }
+       psStubPBDesc->hDevCookie = hDevCookie;
+
+
+       List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
+                                                                       psStubPBDesc);
+
+       *phSharedPBDesc = (IMG_HANDLE)psResItem;
+
+       return PVRSRV_OK;
+
+NoAdd:
+       if(psStubPBDesc)
+       {
+               if(psStubPBDesc->ppsSubKernelMemInfos)
+               {
+                       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                         sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+                                         psStubPBDesc->ppsSubKernelMemInfos,
+                                         0);
+                       psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+               }
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_STUB_PBDESC),
+                                 psStubPBDesc,
+                                 0);
+
+       }
+
+NoAddKeepPB:
+       for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
+       {
+               PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]);
+       }
+
+       PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
+       PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
+
+       PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
+       PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo);
+
+       return eRet;
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
new file mode 100644 (file)
index 0000000..1014954
--- /dev/null
@@ -0,0 +1,146 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_KM_H__)
+#define __SGX_BRIDGE_KM_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sgx_bridge.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick,
+                                PVRSRV_PER_PROCESS_DATA *proc);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick,
+                        PVRSRV_PER_PROCESS_DATA *proc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM(IMG_HANDLE hDevMemHeap,
+                                                                 IMG_DEV_VIRTADDR sDevVAddr,
+                                                                 IMG_DEV_PHYADDR *pDevPAddr,
+                                                                 IMG_CPU_PHYADDR *pCpuPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV SGXGetMMUPDAddrKM(IMG_HANDLE         hDevCookie,
+                                                                                       IMG_HANDLE              hDevMemContext,
+                                                                                       IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE                             hDevCookie,
+                                                               SGX_CLIENT_INFO*        psClientInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO       *psDevInfo,
+                                                         SGX_MISC_INFO                 *psMiscInfo,
+                                                         PVRSRV_DEVICE_NODE    *psDeviceNode,
+                                                         IMG_HANDLE                     hDevMemContext);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE                                      hDevHandle,
+                                                          IMG_UINT32                                   ui32ArraySize,
+                                                          PVRSRV_SGX_HWPERF_CB_ENTRY   *psHWPerfCBData,
+                                                          IMG_UINT32                                   *pui32DataCount,
+                                                          IMG_UINT32                                   *pui32ClockSpeed,
+                                                          IMG_UINT32                                   *pui32HostTimeStamp);
+
+IMG_IMPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO              *psDevInfo,
+                                                                          PVRSRV_KERNEL_SYNC_INFO      *psSyncInfo,
+                                                                          IMG_BOOL bWaitForComplete);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle,
+                                                                       SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                                          IMG_HANDLE hDevHandle,
+                                                          SGX_BRIDGE_INIT_INFO *psInitInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA  *psPerProc,
+                                         IMG_HANDLE                            hDevCookie,
+                                         IMG_BOOL                              bLockOnFailure,
+                                         IMG_UINT32                            ui32TotalPBSize,
+                                         IMG_HANDLE                            *phSharedPBDesc,
+                                         PVRSRV_KERNEL_MEM_INFO        **ppsSharedPBDescKernelMemInfo,
+                                         PVRSRV_KERNEL_MEM_INFO        **ppsHWPBDescKernelMemInfo,
+                                         PVRSRV_KERNEL_MEM_INFO        **ppsBlockKernelMemInfo,
+                                         PVRSRV_KERNEL_MEM_INFO        **ppsHWBlockKernelMemInfo,
+                                         PVRSRV_KERNEL_MEM_INFO        ***pppsSharedPBDescSubKernelMemInfos,
+                                         IMG_UINT32                            *ui32SharedPBDescSubKernelMemInfosCount);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA   *psPerProc,
+                                        IMG_HANDLE                             hDevCookie,
+                                        PVRSRV_KERNEL_MEM_INFO         *psSharedPBDescKernelMemInfo,
+                                        PVRSRV_KERNEL_MEM_INFO         *psHWPBDescKernelMemInfo,
+                                        PVRSRV_KERNEL_MEM_INFO         *psBlockKernelMemInfo,
+                                        PVRSRV_KERNEL_MEM_INFO         *psHWBlockKernelMemInfo,
+                                        IMG_UINT32                                     ui32TotalPBSize,
+                                        IMG_HANDLE                                     *phSharedPBDesc,
+                                        PVRSRV_KERNEL_MEM_INFO         **psSharedPBDescSubKernelMemInfos,
+                                        IMG_UINT32                                     ui32SharedPBDescSubKernelMemInfosCount);
+
+
+IMG_IMPORT PVRSRV_ERROR
+SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+                                               SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo);
+
+extern PVRSRV_SGXDEV_INFO      *pvr_sgx_dev_info;
+
+PVRSRV_SGXDEV_INFO *__pvr_get_sgx_dev_info(void);
+static inline PVRSRV_SGXDEV_INFO *pvr_get_sgx_dev_info(void)
+{
+       if (pvr_sgx_dev_info)
+               return pvr_sgx_dev_info;
+
+       return __pvr_get_sgx_dev_info();
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxconfig.h b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxconfig.h
new file mode 100644 (file)
index 0000000..f46a5c2
--- /dev/null
@@ -0,0 +1,239 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __SGXCONFIG_H__
+#define __SGXCONFIG_H__
+
+#include "sgxdefs.h"
+
+#define DEV_DEVICE_TYPE                        PVRSRV_DEVICE_TYPE_SGX
+#define DEV_DEVICE_CLASS               PVRSRV_DEVICE_CLASS_3D
+
+#define DEV_MAJOR_VERSION              1
+#define DEV_MINOR_VERSION              0
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
+       #if defined(SGX_FEATURE_2D_HARDWARE)
+       #define SGX_2D_HEAP_BASE                                         0x00100000
+       #define SGX_2D_HEAP_SIZE                                        (0x08000000-0x00100000-0x00001000)
+       #else
+               #if defined(FIX_HW_BRN_26915)
+               #define SGX_CGBUFFER_HEAP_BASE                                   0x00100000
+               #define SGX_CGBUFFER_HEAP_SIZE                                  (0x08000000-0x00100000-0x00001000)
+               #endif
+       #endif
+
+       #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+       #define SGX_GENERAL_MAPPING_HEAP_BASE            0x08000000
+       #define SGX_GENERAL_MAPPING_HEAP_SIZE           (0x20000000-0x00001000)
+       #endif
+
+       #define SGX_GENERAL_HEAP_BASE                            0x28000000
+       #define SGX_GENERAL_HEAP_SIZE                           (0xAA000000-0x00001000)
+
+       #define SGX_3DPARAMETERS_HEAP_BASE                       0xD2000000
+       #define SGX_3DPARAMETERS_HEAP_SIZE                      (0x10000000-0x00001000)
+
+       #define SGX_TADATA_HEAP_BASE                             0xE2000000
+       #define SGX_TADATA_HEAP_SIZE                            (0x0D000000-0x00001000)
+
+       #define SGX_SYNCINFO_HEAP_BASE                           0xEF000000
+       #define SGX_SYNCINFO_HEAP_SIZE                          (0x01000000-0x00001000)
+
+       #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE          0xF0000000
+       #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE         (0x02000000-0x00001000)
+
+       #define SGX_KERNEL_CODE_HEAP_BASE                        0xF2000000
+       #define SGX_KERNEL_CODE_HEAP_SIZE                       (0x00080000-0x00001000)
+
+       #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE         0xF2400000
+       #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE        (0x01C00000-0x00001000)
+
+       #define SGX_KERNEL_DATA_HEAP_BASE                       (0xF4000000)
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+   #define SGX_KERNEL_DATA_HEAP_SIZE                   (0x05000000-0x00002000)
+#else
+       #define SGX_KERNEL_DATA_HEAP_SIZE                       (0x05000000-0x00001000)
+#endif
+
+       #define SGX_PIXELSHADER_HEAP_BASE                        0xF9000000
+       #define SGX_PIXELSHADER_HEAP_SIZE                       (0x05000000-0x00001000)
+       
+       #define SGX_VERTEXSHADER_HEAP_BASE                       0xFE000000
+       #define SGX_VERTEXSHADER_HEAP_SIZE                      (0x02000000-0x00001000)
+
+       
+       #define SGX_CORE_IDENTIFIED
+#endif 
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+       #define SGX_GENERAL_MAPPING_HEAP_BASE            0x00001000
+       #define SGX_GENERAL_MAPPING_HEAP_SIZE           (0x01800000-0x00001000-0x00001000)
+               
+       #define SGX_GENERAL_HEAP_BASE                            0x01800000
+       #define SGX_GENERAL_HEAP_SIZE                           (0x07000000-0x00001000)
+
+#else
+       #define SGX_GENERAL_HEAP_BASE                            0x00001000
+       #define SGX_GENERAL_HEAP_SIZE                           (0x0C000000-0x00001000-0x00001000)
+#endif
+
+       #define SGX_3DPARAMETERS_HEAP_BASE                       0x0C000000
+       #define SGX_3DPARAMETERS_HEAP_SIZE                      (0x00800000-0x00001000)
+
+       #define SGX_TADATA_HEAP_BASE                             0x0C800000
+       #define SGX_TADATA_HEAP_SIZE                            (0x01000000-0x00001000)
+
+       #define SGX_SYNCINFO_HEAP_BASE                           0x0D800000
+       #define SGX_SYNCINFO_HEAP_SIZE                          (0x00400000-0x00001000)
+
+       #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE          0x0DC00000
+       #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE         (0x00800000-0x00001000)
+
+       #define SGX_KERNEL_CODE_HEAP_BASE                        0x0E400000
+       #define SGX_KERNEL_CODE_HEAP_SIZE                       (0x00080000-0x00001000)
+
+       #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE         0x0E800000
+       #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE        (0x00800000-0x00001000)
+
+       #define SGX_KERNEL_DATA_HEAP_BASE                       (0x0F000000)
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+       #define SGX_KERNEL_DATA_HEAP_SIZE                       (0x00400000-0x00002000)
+#else
+       #define SGX_KERNEL_DATA_HEAP_SIZE                       (0x00400000-0x00001000)
+#endif
+
+       #define SGX_PIXELSHADER_HEAP_BASE                        0x0F400000
+       #define SGX_PIXELSHADER_HEAP_SIZE                       (0x00500000-0x00001000)
+
+       #define SGX_VERTEXSHADER_HEAP_BASE                       0x0FC00000
+       #define SGX_VERTEXSHADER_HEAP_SIZE                      (0x00200000-0x00001000)
+
+       
+       #define SGX_CORE_IDENTIFIED
+
+#endif 
+
+#if !defined(SGX_CORE_IDENTIFIED)
+       #error "sgxconfig.h: ERROR: unspecified SGX Core version"
+#endif
+
+#if !defined (SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE)
+       #if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) >  0x4000000)
+               #error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+       #endif
+       
+       #if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) >  0x4000000)
+               #error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+       #endif
+#endif 
+
+#if defined(SGX_FEATURE_2D_HARDWARE) && defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+       #if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE - SGX_2D_HEAP_BASE) >= EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK)
+               #error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP inaccessable by 2D requestor"
+       #endif
+#endif
+
+#if defined (EURASIA_USE_CODE_PAGE_SIZE)
+       #if ((SGX_KERNEL_CODE_HEAP_BASE & (EURASIA_USE_CODE_PAGE_SIZE - 1)) != 0)
+               #error "sgxconfig.h: ERROR: Kernel code heap base misalignment"
+       #endif
+#endif
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+       #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+               #if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
+                       #error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
+               #endif
+       #else
+               #if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+                       #error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_HEAP_BASE"
+               #endif
+       #endif
+#else
+    #if defined(FIX_HW_BRN_26915)
+               #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+                       #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
+                               #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
+                       #endif
+               #else
+                       #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+                               #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_HEAP_BASE"
+                       #endif
+               #endif
+       #endif
+#endif
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+       #if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+               #error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP overlaps SGX_GENERAL_HEAP"
+       #endif
+#endif
+
+#if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_3DPARAMETERS_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+#endif
+
+#if ((SGX_3DPARAMETERS_HEAP_BASE + SGX_3DPARAMETERS_HEAP_SIZE) >= SGX_TADATA_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_3DPARAMETERS_HEAP overlaps SGX_TADATA_HEAP"
+#endif
+
+#if ((SGX_TADATA_HEAP_BASE + SGX_TADATA_HEAP_SIZE) >= SGX_SYNCINFO_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_TADATA_HEAP overlaps SGX_SYNCINFO_HEAP"
+#endif
+
+#if ((SGX_SYNCINFO_HEAP_BASE + SGX_SYNCINFO_HEAP_SIZE) >= SGX_PDSPIXEL_CODEDATA_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_SYNCINFO_HEAP overlaps SGX_PDSPIXEL_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSPIXEL_CODEDATA_HEAP_BASE + SGX_PDSPIXEL_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_CODE_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_PDSPIXEL_CODEDATA_HEAP overlaps SGX_KERNEL_CODE_HEAP"
+#endif
+
+#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE) >= SGX_PDSVERTEX_CODEDATA_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP overlaps SGX_PDSVERTEX_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_DATA_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP overlaps SGX_KERNEL_DATA_HEAP"
+#endif
+
+#if ((SGX_KERNEL_DATA_HEAP_BASE + SGX_KERNEL_DATA_HEAP_SIZE) >= SGX_PIXELSHADER_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_KERNEL_DATA_HEAP overlaps SGX_PIXELSHADER_HEAP"
+#endif
+
+#if ((SGX_PIXELSHADER_HEAP_BASE + SGX_PIXELSHADER_HEAP_SIZE) >= SGX_VERTEXSHADER_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_PIXELSHADER_HEAP overlaps SGX_VERTEXSHADER_HEAP"
+#endif
+
+#if ((SGX_VERTEXSHADER_HEAP_BASE + SGX_VERTEXSHADER_HEAP_SIZE) < SGX_VERTEXSHADER_HEAP_BASE)
+       #error "sgxconfig.h: ERROR: SGX_VERTEXSHADER_HEAP_BASE size cause wraparound"
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxinfokm.h b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
new file mode 100644 (file)
index 0000000..e662df0
--- /dev/null
@@ -0,0 +1,377 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __SGXINFOKM_H__
+#define __SGXINFOKM_H__
+
+#include "sgxdefs.h"
+#include "device.h"
+#include "power.h"
+#include "sysconfig.h"
+#include "sgxscript.h"
+#include "sgxinfo.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define                SGX_HOSTPORT_PRESENT                    0x00000001UL
+
+
+#define SGX_PDUMPREG_NAME              "SGXREG"
+
+typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+
+
+typedef struct _PVRSRV_SGX_CCB_INFO_ *PPVRSRV_SGX_CCB_INFO;
+
+typedef struct _PVRSRV_SGXDEV_INFO_
+{
+       PVRSRV_DEVICE_TYPE              eDeviceType;
+       PVRSRV_DEVICE_CLASS             eDeviceClass;
+
+       IMG_UINT8                               ui8VersionMajor;
+       IMG_UINT8                               ui8VersionMinor;
+       IMG_UINT32                              ui32CoreConfig;
+       IMG_UINT32                              ui32CoreFlags;
+
+       
+       IMG_PVOID                               pvRegsBaseKM;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+       
+       IMG_PVOID                               pvHostPortBaseKM;
+       
+       IMG_UINT32                              ui32HPSize;
+       
+       IMG_SYS_PHYADDR                 sHPSysPAddr;
+#endif
+
+       
+       IMG_HANDLE                              hRegMapping;
+
+       
+       IMG_SYS_PHYADDR                 sRegsPhysBase;
+       
+       IMG_UINT32                              ui32RegSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+       
+       IMG_UINT32                              ui32ExtSysCacheRegsSize;
+       
+       IMG_DEV_PHYADDR                 sExtSysCacheRegsDevPBase;
+       
+       IMG_UINT32                              *pui32ExtSystemCacheRegsPT;
+       
+       IMG_HANDLE                              hExtSystemCacheRegsPTPageOSMemHandle;
+       
+       IMG_SYS_PHYADDR                 sExtSystemCacheRegsPTSysPAddr;
+#endif
+
+       
+       IMG_UINT32                              ui32CoreClockSpeed;
+       IMG_UINT32                              ui32uKernelTimerClock;
+
+       PVRSRV_STUB_PBDESC              *psStubPBDescListKM;
+
+
+       
+       IMG_DEV_PHYADDR                 sKernelPDDevPAddr;
+
+       IMG_VOID                                *pvDeviceMemoryHeap;
+       PPVRSRV_KERNEL_MEM_INFO psKernelCCBMemInfo;                     
+       PVRSRV_SGX_KERNEL_CCB   *psKernelCCB;                   
+       PPVRSRV_SGX_CCB_INFO    psKernelCCBInfo;                
+       PPVRSRV_KERNEL_MEM_INFO psKernelCCBCtlMemInfo;  
+       PVRSRV_SGX_CCB_CTL              *psKernelCCBCtl;                
+       PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo; 
+       IMG_UINT32                              *pui32KernelCCBEventKicker; 
+#if defined(PDUMP)
+       IMG_UINT32                              ui32KernelCCBEventKickerDumpVal; 
+#endif 
+       PVRSRV_KERNEL_MEM_INFO  *psKernelSGXMiscMemInfo;        
+       IMG_UINT32                              aui32HostKickAddr[SGXMKIF_CMD_MAX];             
+#if defined(SGX_SUPPORT_HWPROFILING)
+       PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
+#endif
+       PPVRSRV_KERNEL_MEM_INFO         psKernelHWPerfCBMemInfo;                
+       PPVRSRV_KERNEL_MEM_INFO         psKernelTASigBufferMemInfo;             
+       PPVRSRV_KERNEL_MEM_INFO         psKernel3DSigBufferMemInfo;             
+#if defined(FIX_HW_BRN_29702)
+       PPVRSRV_KERNEL_MEM_INFO psKernelCFIMemInfo;     
+#endif
+#if defined(FIX_HW_BRN_29823)
+       PPVRSRV_KERNEL_MEM_INFO psKernelDummyTermStreamMemInfo; 
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+       PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo; 
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+       PPVRSRV_KERNEL_MEM_INFO psKernelTmpRgnHeaderMemInfo; 
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+       PPVRSRV_KERNEL_MEM_INFO psKernelTmpDPMStateMemInfo; 
+#endif
+
+       
+       IMG_UINT32                              ui32ClientRefCount;
+
+       
+       IMG_UINT32                              ui32CacheControl;
+
+       
+       IMG_UINT32                              ui32ClientBuildOptions;
+
+       
+       SGX_MISCINFO_STRUCT_SIZES       sSGXStructSizes;
+
+       
+
+
+       IMG_VOID                                *pvMMUContextList;
+
+       
+       IMG_BOOL                                bForcePTOff;
+
+       IMG_UINT32                              ui32EDMTaskReg0;
+       IMG_UINT32                              ui32EDMTaskReg1;
+
+       IMG_UINT32                              ui32ClkGateStatusReg;
+       IMG_UINT32                              ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+       IMG_UINT32                              ui32MasterClkGateStatusReg;
+       IMG_UINT32                              ui32MasterClkGateStatusMask;
+       IMG_UINT32                              ui32MasterClkGateStatus2Reg;
+       IMG_UINT32                              ui32MasterClkGateStatus2Mask;
+#endif 
+       SGX_INIT_SCRIPTS                sScripts;
+
+       
+       IMG_HANDLE                              hBIFResetPDOSMemHandle;
+       IMG_DEV_PHYADDR                 sBIFResetPDDevPAddr;
+       IMG_DEV_PHYADDR                 sBIFResetPTDevPAddr;
+       IMG_DEV_PHYADDR                 sBIFResetPageDevPAddr;
+       IMG_UINT32                              *pui32BIFResetPD;
+       IMG_UINT32                              *pui32BIFResetPT;
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+       
+       IMG_HANDLE                              hBRN22997PTPageOSMemHandle;
+       IMG_HANDLE                              hBRN22997PDPageOSMemHandle;
+       IMG_DEV_PHYADDR                 sBRN22997PTDevPAddr;
+       IMG_DEV_PHYADDR                 sBRN22997PDDevPAddr;
+       IMG_UINT32                              *pui32BRN22997PT;
+       IMG_UINT32                              *pui32BRN22997PD;
+       IMG_SYS_PHYADDR                 sBRN22997SysPAddr;
+#endif 
+
+#if defined(SUPPORT_HW_RECOVERY)
+       
+       IMG_HANDLE                              hTimer;
+       
+       IMG_UINT32                              ui32TimeStamp;
+#endif
+
+       
+       IMG_UINT32                              ui32NumResets;
+
+       
+       PVRSRV_KERNEL_MEM_INFO                  *psKernelSGXHostCtlMemInfo;
+       SGXMKIF_HOST_CTL                                *psSGXHostCtl;
+
+       
+       PVRSRV_KERNEL_MEM_INFO                  *psKernelSGXTA3DCtlMemInfo;
+
+       IMG_UINT32                              ui32Flags;
+
+       
+       IMG_UINT32                              ui32MemTilingUsage;
+
+       #if defined(PDUMP)
+       PVRSRV_SGX_PDUMP_CONTEXT        sPDContext;
+       #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+       
+       IMG_VOID                                *pvDummyPTPageCpuVAddr;
+       IMG_DEV_PHYADDR                 sDummyPTDevPAddr;
+       IMG_HANDLE                              hDummyPTPageOSMemHandle;
+       IMG_VOID                                *pvDummyDataPageCpuVAddr;
+       IMG_DEV_PHYADDR                 sDummyDataDevPAddr;
+       IMG_HANDLE                              hDummyDataPageOSMemHandle;
+#endif
+#if defined(PDUMP)
+       PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+       IMG_UINT32                              asSGXDevData[SGX_MAX_DEV_DATA];
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       PVRSRV_KERNEL_MEM_INFO*                  psResProfMemInfo;
+       IMG_UINT32*                              pui32UsedMem;
+
+#endif
+} PVRSRV_SGXDEV_INFO;
+
+
+typedef struct _SGX_TIMING_INFORMATION_
+{
+       IMG_UINT32                      ui32CoreClockSpeed;
+       IMG_UINT32                      ui32HWRecoveryFreq;
+       IMG_BOOL                        bEnableActivePM;
+       IMG_UINT32                      ui32ActivePowManLatencyms;
+       IMG_UINT32                      ui32uKernelFreq;
+} SGX_TIMING_INFORMATION;
+
+typedef struct _SGX_DEVICE_MAP_
+{
+       IMG_UINT32                              ui32Flags;
+
+       
+       IMG_SYS_PHYADDR                 sRegsSysPBase;
+       IMG_CPU_PHYADDR                 sRegsCpuPBase;
+       IMG_CPU_VIRTADDR                pvRegsCpuVBase;
+       IMG_UINT32                              ui32RegsSize;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+       IMG_SYS_PHYADDR                 sHPSysPBase;
+       IMG_CPU_PHYADDR                 sHPCpuPBase;
+       IMG_UINT32                              ui32HPSize;
+#endif
+
+       
+       IMG_SYS_PHYADDR                 sLocalMemSysPBase;
+       IMG_DEV_PHYADDR                 sLocalMemDevPBase;
+       IMG_CPU_PHYADDR                 sLocalMemCpuPBase;
+       IMG_UINT32                              ui32LocalMemSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+       IMG_UINT32                              ui32ExtSysCacheRegsSize;
+       IMG_DEV_PHYADDR                 sExtSysCacheRegsDevPBase;
+#endif
+
+       
+       IMG_UINT32                              ui32IRQ;
+
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+       
+       SGX_TIMING_INFORMATION  sTimingInfo;
+#endif
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       IMG_UINT32              ui32MemThreshold;
+#endif
+#if defined(PDUMP)
+       
+       IMG_CHAR                                *pszPDumpDevName;
+#endif
+} SGX_DEVICE_MAP;
+
+
+struct _PVRSRV_STUB_PBDESC_
+{
+       IMG_UINT32              ui32RefCount;
+       IMG_UINT32              ui32TotalPBSize;
+       PVRSRV_KERNEL_MEM_INFO  *psSharedPBDescKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO  *psHWPBDescKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO  **ppsSubKernelMemInfos;
+       IMG_UINT32              ui32SubKernelMemInfosCount;
+       IMG_HANDLE              hDevCookie;
+       PVRSRV_KERNEL_MEM_INFO  *psBlockKernelMemInfo;
+       PVRSRV_KERNEL_MEM_INFO  *psHWBlockKernelMemInfo;
+       PVRSRV_STUB_PBDESC      *psNext;
+       PVRSRV_STUB_PBDESC      **ppsThis;
+};
+
+typedef struct _PVRSRV_SGX_CCB_INFO_
+{
+       PVRSRV_KERNEL_MEM_INFO  *psCCBMemInfo;                  
+       PVRSRV_KERNEL_MEM_INFO  *psCCBCtlMemInfo;               
+       SGXMKIF_COMMAND         *psCommands;                    
+       IMG_UINT32                              *pui32WriteOffset;              
+       volatile IMG_UINT32             *pui32ReadOffset;               
+#if defined(PDUMP)
+       IMG_UINT32                              ui32CCBDumpWOff;                
+#endif
+} PVRSRV_SGX_CCB_INFO;
+
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SGXOSTimer(IMG_VOID *pvData);
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO   *psDevInfo,
+                                 IMG_BOOL                              bHardwareRecovery,
+                                 IMG_UINT32                    ui32PDUMPFlags);
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO  *psDevInfo,
+                                                  IMG_BOOL                             bHardwareRecovery);
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+
+PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE                               hDevHandle, 
+                                                         PVRSRV_DEV_POWER_STATE        eNewPowerState, 
+                                                         PVRSRV_DEV_POWER_STATE        eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE                              hDevHandle, 
+                                                          PVRSRV_DEV_POWER_STATE       eNewPowerState, 
+                                                          PVRSRV_DEV_POWER_STATE       eCurrentPowerState);
+
+PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE                         hDevHandle,
+                                                                       IMG_BOOL                                bIdleDevice,
+                                                                       PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE                                hDevHandle,
+                                                                        IMG_BOOL                               bIdleDevice,
+                                                                        PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO   *psDevInfo);
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo);
+#endif
+
+#if defined(NO_HARDWARE)
+static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO              *psDevInfo,
+                                                                                               IMG_UINT32 ui32StatusRegister,
+                                                                                               IMG_UINT32 ui32StatusValue,
+                                                                                               IMG_UINT32 ui32StatusMask)
+{
+       IMG_UINT32 ui32RegVal;
+
+       ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister);
+
+       ui32RegVal &= ~ui32StatusMask;
+       ui32RegVal |= (ui32StatusValue & ui32StatusMask);
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister, ui32RegVal);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxinit.c b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxinit.c
new file mode 100644 (file)
index 0000000..a00550b
--- /dev/null
@@ -0,0 +1,2787 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sgxconfig.h"
+#include "sysconfig.h"
+#include "pvr_bridge_km.h"
+
+#include "sgx_bridge_km.h"
+
+#include "pdump_km.h"
+#include "ra.h"
+#include "mmu.h"
+#include "handle.h"
+#include "perproc.h"
+
+#include "sgxutils.h"
+#include "pvrversion.h"
+#include "sgx_options.h"
+
+#include "lists.h"
+#include "srvkm.h"
+#include "pvr_trace_cmd.h"
+
+#define VAR(x) #x
+
+#define CHECK_SIZE(NAME) \
+{      \
+       if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \
+       {       \
+               PVR_DPF((PVR_DBG_ERROR, "SGXDevInitCompatCheck: Size check failed for SGXMKIF_%s (client) = %d bytes, (ukernel) = %d bytes\n", \
+                       VAR(NAME), \
+                       psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME, \
+                       psSGXStructSizes->ui32Sizeof_##NAME )); \
+               bStructSizesFailed = IMG_TRUE; \
+       }       \
+}
+
+#if defined (SYS_USING_INTERRUPTS)
+IMG_BOOL SGX_ISRHandler(IMG_VOID *pvData);
+#endif
+
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO  *psDevInfo,
+                                                                  PVRSRV_DEVICE_NODE   *psDeviceNode);
+#if defined(PDUMP)
+static
+PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(OS_SUPPORTS_IN_LISR)
+       if (OSInLISR(psDeviceNode->psSysData))
+       {
+               
+               psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+       }
+       else
+       {
+               SGXScheduleProcessQueuesKM(psDeviceNode);
+       }
+#else
+       SGXScheduleProcessQueuesKM(psDeviceNode);
+#endif
+}
+
+static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+       if (psDevInfo->psKernelCCBInfo != IMG_NULL)
+       {
+               
+
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL);
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_SGXDEV_INFO *pvr_sgx_dev_info;
+
+PVRSRV_SGXDEV_INFO *__pvr_get_sgx_dev_info(void)
+{
+       PVRSRV_DEVICE_NODE      *dev_node;
+       PVRSRV_ERROR            err;
+
+       err = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_SGX,
+                                       (IMG_HANDLE)&dev_node);
+       if (err != PVRSRV_OK || !dev_node || !dev_node->pvDevice) {
+               WARN_ONCE(1, "pvr: can't get SGX device info\n");
+
+               return NULL;
+       }
+
+       pvr_sgx_dev_info = dev_node->pvDevice;
+
+       return pvr_sgx_dev_info;
+}
+
+static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                                               PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                               SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+       PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+       PVRSRV_ERROR            eError;
+
+       PVRSRV_SGX_CCB_INFO     *psKernelCCBInfo = IMG_NULL;
+
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+       psDevInfo->sScripts = psInitInfo->sScripts;
+
+       psDevInfo->psKernelCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
+       psDevInfo->psKernelCCB = (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->pvLinAddrKM;
+
+       psDevInfo->psKernelCCBCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
+       psDevInfo->psKernelCCBCtl = (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->pvLinAddrKM;
+
+       psDevInfo->psKernelCCBEventKickerMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBEventKickerMemInfo;
+       psDevInfo->pui32KernelCCBEventKicker = (IMG_UINT32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
+
+       psDevInfo->psKernelSGXHostCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXHostCtlMemInfo;
+       psDevInfo->psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+       psDevInfo->psKernelSGXTA3DCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXTA3DCtlMemInfo;
+
+       psDevInfo->psKernelSGXMiscMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+       psDevInfo->psKernelHWProfilingMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+       psDevInfo->psKernelHWPerfCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
+#endif
+       psDevInfo->psKernelTASigBufferMemInfo = psInitInfo->hKernelTASigBufferMemInfo;
+       psDevInfo->psKernel3DSigBufferMemInfo = psInitInfo->hKernel3DSigBufferMemInfo;
+#if defined(FIX_HW_BRN_29702)
+       psDevInfo->psKernelCFIMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCFIMemInfo;
+#endif
+#if defined(FIX_HW_BRN_29823)
+       psDevInfo->psKernelDummyTermStreamMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelDummyTermStreamMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+       psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+       psDevInfo->psKernelTmpRgnHeaderMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+       psDevInfo->psKernelTmpDPMStateMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpDPMStateMemInfo;
+#endif
+       
+       psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions;
+
+       
+       psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes;
+
+
+       
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof(PVRSRV_SGX_CCB_INFO),
+                                               (IMG_VOID **)&psKernelCCBInfo, 0,
+                                               "SGX Circular Command Buffer Info");
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory"));
+               goto failed_allockernelccb;
+       }
+
+
+       OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO));
+       psKernelCCBInfo->psCCBMemInfo           = psDevInfo->psKernelCCBMemInfo;
+       psKernelCCBInfo->psCCBCtlMemInfo        = psDevInfo->psKernelCCBCtlMemInfo;
+       psKernelCCBInfo->psCommands                     = psDevInfo->psKernelCCB->asCommands;
+       psKernelCCBInfo->pui32WriteOffset       = &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+       psKernelCCBInfo->pui32ReadOffset        = &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
+       psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
+
+       
+
+       OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr,
+                         SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0]));
+
+       psDevInfo->bForcePTOff = IMG_FALSE;
+
+       psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
+
+       psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
+       psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
+       psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
+       psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+       psDevInfo->ui32MasterClkGateStatusReg = psInitInfo->ui32MasterClkGateStatusReg;
+       psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask;
+       psDevInfo->ui32MasterClkGateStatus2Reg = psInitInfo->ui32MasterClkGateStatus2Reg;
+       psDevInfo->ui32MasterClkGateStatus2Mask = psInitInfo->ui32MasterClkGateStatus2Mask;
+#endif 
+
+
+       
+       OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData));
+
+       return PVRSRV_OK;
+
+failed_allockernelccb:
+       DeinitDevInfo(psDevInfo);
+
+       return eError;
+}
+
+
+
+
+static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND *psScript, IMG_UINT32 ui32NumInitCommands)
+{
+       IMG_UINT32 ui32PC;
+       SGX_INIT_COMMAND *psComm;
+
+       for (ui32PC = 0, psComm = psScript;
+               ui32PC < ui32NumInitCommands;
+               ui32PC++, psComm++)
+       {
+               switch (psComm->eOp)
+               {
+                       case SGX_INIT_OP_WRITE_HW_REG:
+                       {
+                               OSWriteHWReg(psDevInfo->pvRegsBaseKM, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+                               PDUMPCOMMENT("SGXRunScript: Write HW reg operation");
+                               PDUMPREG(SGX_PDUMPREG_NAME, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+                               break;
+                       }
+#if defined(PDUMP)
+                       case SGX_INIT_OP_PDUMP_HW_REG:
+                       {
+                               PDUMPCOMMENT("SGXRunScript: Dump HW reg operation");
+                               PDUMPREG(SGX_PDUMPREG_NAME, psComm->sPDumpHWReg.ui32Offset, psComm->sPDumpHWReg.ui32Value);
+                               break;
+                       }
+#endif
+                       case SGX_INIT_OP_HALT:
+                       {
+                               return PVRSRV_OK;
+                       }
+                       case SGX_INIT_OP_ILLEGAL:
+                       
+                       default:
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
+                               return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+                       }
+               }
+
+       }
+
+       return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+}
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO  *psDevInfo,
+                                                  IMG_BOOL                             bHardwareRecovery)
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_KERNEL_MEM_INFO  *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+       SGXMKIF_HOST_CTL                *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+       static IMG_BOOL                 bFirstTime = IMG_TRUE;
+#if defined(PDUMP)
+       IMG_BOOL                                bPDumpIsSuspended = PDumpIsSuspended();
+#endif 
+
+       
+
+       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n");
+       eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 1) failed (%d)", eError));
+               return eError;
+       }
+       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n");
+
+       
+       SGXReset(psDevInfo, bFirstTime || bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(EUR_CR_POWER)
+#if defined(SGX531)
+       
+
+
+
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
+       PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 1);
+#else
+       
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
+       PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 0);
+#endif
+#endif
+
+       
+       *psDevInfo->pui32KernelCCBEventKicker = 0;
+#if defined(PDUMP)
+       if (!bPDumpIsSuspended)
+       {
+               psDevInfo->ui32KernelCCBEventKickerDumpVal = 0;
+               PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+                                psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+                                sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS,
+                                MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+       }
+#endif 
+
+       
+
+       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n");
+       eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 2) failed (%d)", eError));
+               return eError;
+       }
+       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n");
+
+       
+       psSGXHostCtl->ui32HostClock = OSClockus();
+
+       psSGXHostCtl->ui32InitStatus = 0;
+#if defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+                                                 "Reset the SGX microkernel initialisation status\n");
+       PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+                        offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+                        sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                        MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+                                                 "Initialise the microkernel\n");
+#endif 
+
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+       OSWriteMemoryBarrier();
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+                                SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+                                EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+       *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+       OSWriteMemoryBarrier();
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+                                SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+                                EUR_CR_EVENT_KICK_NOW_MASK);
+#endif 
+
+       OSMemoryBarrier();
+
+#if defined(PDUMP)
+       
+
+       if (!bPDumpIsSuspended)
+       {
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+               PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+               psDevInfo->ui32KernelCCBEventKickerDumpVal = 1;
+               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+                                                         "First increment of the SGX event kicker value\n");
+               PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+                                psDevInfo->psKernelCCBEventKickerMemInfo,
+                                0,
+                                sizeof(IMG_UINT32),
+                                PDUMP_FLAGS_CONTINUOUS,
+                                MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+               PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK);
+#endif 
+       }
+#endif 
+
+#if !defined(NO_HARDWARE)
+       
+
+       if (PollForValueKM(&psSGXHostCtl->ui32InitStatus,
+                                          PVRSRV_USSE_EDM_INIT_COMPLETE,
+                                          PVRSRV_USSE_EDM_INIT_COMPLETE,
+                                          MAX_HW_TIME_US,
+                                          MAX_HW_TIME_US/WAIT_TRY_COUNT,
+                                          IMG_FALSE) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed"));
+               #if !defined(FIX_HW_BRN_23281)
+               PVR_DBG_BREAK;
+               #endif
+               return PVRSRV_ERROR_RETRY;
+       }
+#endif 
+
+#if defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+                                                 "Wait for the SGX microkernel initialisation to complete");
+       PDUMPMEMPOL(psSGXHostCtlMemInfo,
+                               offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+                               PVRSRV_USSE_EDM_INIT_COMPLETE,
+                               PVRSRV_USSE_EDM_INIT_COMPLETE,
+                               PDUMP_POLL_OPERATOR_EQUAL,
+                               PDUMP_FLAGS_CONTINUOUS,
+                               MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+#endif 
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+       
+
+
+       WorkaroundBRN22997ReadHostPort(psDevInfo);
+#endif 
+
+       PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset);
+
+       bFirstTime = IMG_FALSE;
+       
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
+
+{
+       PVRSRV_SGXDEV_INFO      *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
+       PVRSRV_ERROR            eError;
+
+       
+       if (psDevInfo->pvRegsBaseKM == IMG_NULL)
+       {
+               return PVRSRV_OK;
+       }
+
+       eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands, SGX_MAX_DEINIT_COMMANDS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXDeinitialise: SGXRunScript failed (%d)", eError));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
+{
+       IMG_HANDLE hDevMemHeap = IMG_NULL;
+       PVRSRV_SGXDEV_INFO      *psDevInfo;
+       IMG_HANDLE              hKernelDevMemContext;
+       IMG_DEV_PHYADDR         sPDDevPAddr;
+       IMG_UINT32              i;
+       PVRSRV_DEVICE_NODE  *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+       PVRSRV_ERROR            eError;
+
+       
+       PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME);
+       
+       #if defined(SGX_FEATURE_MP)
+       PDUMPCOMMENT("SGX Multi-processor: %d cores", SGX_FEATURE_MP_CORE_COUNT);
+       #endif 
+
+#if (SGX_CORE_REV == 0)
+       PDUMPCOMMENT("SGX Core Revision Information: head RTL");
+#else
+       PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
+#endif
+
+       #if defined(SGX_FEATURE_SYSTEM_CACHE)
+       PDUMPCOMMENT("SGX System Level Cache is present\r\n");
+       #if defined(SGX_BYPASS_SYSTEM_CACHE)
+       PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n");
+       #endif 
+       #endif 
+
+       PDUMPCOMMENT("SGX Initialisation Part 1");
+
+       
+       if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                        sizeof(PVRSRV_SGXDEV_INFO),
+                                        (IMG_VOID **)&psDevInfo, IMG_NULL,
+                                        "SGX Device Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1 : Failed to alloc memory for DevInfo"));
+               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+       }
+       OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
+
+       
+       psDevInfo->eDeviceType          = DEV_DEVICE_TYPE;
+       psDevInfo->eDeviceClass         = DEV_DEVICE_CLASS;
+
+       
+       psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo;
+
+       
+       psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap;
+
+       
+       hKernelDevMemContext = BM_CreateContext(psDeviceNode,
+                                                                                       &sPDDevPAddr,
+                                                                                       IMG_NULL,
+                                                                                       IMG_NULL);
+       if (hKernelDevMemContext == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1: Failed BM_CreateContext"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
+
+       
+       for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++)
+       {
+               switch(psDeviceMemoryHeap[i].DevMemHeapType)
+               {
+                       case DEVICE_MEMORY_HEAP_KERNEL:
+                       case DEVICE_MEMORY_HEAP_SHARED:
+                       case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+                       {
+                               hDevMemHeap = BM_CreateHeap (hKernelDevMemContext,
+                                                                                               &psDeviceMemoryHeap[i]);
+                               
+
+
+                               psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
+                               break;
+                       }
+               }
+       }
+#if defined(PDUMP)
+       if(hDevMemHeap)
+       {
+               
+               psDevInfo->sMMUAttrib = *((BM_HEAP*)hDevMemHeap)->psMMUAttrib;
+       }
+#endif
+       eError = MMU_BIFResetPDAlloc(psDevInfo);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevInitSGX : Failed to alloc memory for BIF reset"));
+               return eError;
+       }
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                 (IMG_VOID **)&psDevInfo->psResProfMemInfo, IMG_NULL,
+                                 "Res Memory Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory for meminfo"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       OSMemSet(psDevInfo->psResProfMemInfo, 0, sizeof(*psDevInfo->psResProfMemInfo));
+       psDevInfo->psResProfMemInfo->ui32Flags |= PVRSRV_HAP_MULTI_PROCESS | PVRSRV_HAP_UNCACHED;
+       psDevInfo->psResProfMemInfo->ui32AllocSize = sizeof(IMG_UINT32);
+       if(OSAllocPages(psDevInfo->psResProfMemInfo->ui32Flags,
+                               psDevInfo->psResProfMemInfo->ui32AllocSize,
+                               HOST_PAGESIZE(),
+                               &psDevInfo->psResProfMemInfo->pvLinAddrKM,
+                               &psDevInfo->psResProfMemInfo->sMemBlk.hOSMemHandle)
+                               != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory for block"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                 psDevInfo->psResProfMemInfo,
+                                 0);
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       psDevInfo->pui32UsedMem = psDevInfo->psResProfMemInfo->pvLinAddrKM;
+       if(psDevInfo->pui32UsedMem == IMG_NULL)
+               PVR_LOG(("InitDevInfo:res kernel mem info has no kernel address"));
+       *psDevInfo->pui32UsedMem = 0;
+#endif
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
+{
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       PVRSRV_SGXDEV_INFO      *psDevInfo;
+       PVRSRV_ERROR            eError;
+
+       PDUMPCOMMENT("SGXGetInfoForSrvinit");
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+       psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+       psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
+
+       eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)", eError));
+               return eError;
+       }
+
+       return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                IMG_HANDLE hDevHandle,
+                                SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+       PVRSRV_DEVICE_NODE              *psDeviceNode;
+       PVRSRV_SGXDEV_INFO              *psDevInfo;
+       PVRSRV_ERROR                    eError;
+       SGX_DEVICE_MAP                  *psSGXDeviceMap;
+       PVRSRV_DEV_POWER_STATE  eDefaultPowerState;
+
+       PDUMPCOMMENT("SGX Initialisation Part 2");
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+       psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+       eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to load EDM program"));
+               goto failed_init_dev_info;
+       }
+
+
+       eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+                                                                       (IMG_VOID**)&psSGXDeviceMap);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to get device memory map!"));
+               return PVRSRV_ERROR_INIT_FAILURE;
+       }
+
+       
+       if (psSGXDeviceMap->pvRegsCpuVBase)
+       {
+               psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
+       }
+       else
+       {
+               
+               psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
+                                                                                          psSGXDeviceMap->ui32RegsSize,
+                                                                                          PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                          IMG_NULL);
+               if (!psDevInfo->pvRegsBaseKM)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in regs\n"));
+                       return PVRSRV_ERROR_BAD_MAPPING;
+               }
+       }
+       psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
+       psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
+
+
+#if defined(SGX_FEATURE_HOST_PORT)
+       if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+       {
+               
+               psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase,
+                                                                                          psSGXDeviceMap->ui32HPSize,
+                                                                                          PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                          IMG_NULL);
+               if (!psDevInfo->pvHostPortBaseKM)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in host port\n"));
+                       return PVRSRV_ERROR_BAD_MAPPING;
+               }
+               psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize;
+               psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase;
+       }
+#endif
+
+#if defined (SYS_USING_INTERRUPTS)
+
+       
+       psDeviceNode->pvISRData = psDeviceNode;
+       
+       PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
+
+#endif 
+
+       
+       psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+       eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+       
+       eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
+                                                                               &SGXPrePowerState, &SGXPostPowerState,
+                                                                               &SGXPreClockSpeedChange, &SGXPostClockSpeedChange,
+                                                                               (IMG_HANDLE)psDeviceNode,
+                                                                               PVRSRV_DEV_POWER_STATE_OFF,
+                                                                               eDefaultPowerState);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: failed to register device with power manager"));
+               return eError;
+       }
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+       eError = WorkaroundBRN22997Alloc(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to alloc memory for BRN22997 workaround"));
+               return eError;
+       }
+#endif 
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+       
+       psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize;
+       psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase;
+       eError = MMU_MapExtSystemCacheRegs(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers"));
+               return eError;
+       }
+#endif 
+
+       
+
+       OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
+       OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
+       OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker));
+       PDUMPCOMMENT("Initialise Kernel CCB");
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0, sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
+       PDUMPCOMMENT("Initialise Kernel CCB Control");
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0, sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
+       PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+
+       return PVRSRV_OK;
+
+failed_init_dev_info:
+       return eError;
+}
+
+static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
+{
+       PVRSRV_DEVICE_NODE                      *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+       PVRSRV_SGXDEV_INFO                      *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+       PVRSRV_ERROR                            eError;
+       IMG_UINT32                                      ui32Heap;
+       DEVICE_MEMORY_HEAP_INFO         *psDeviceMemoryHeap;
+       SGX_DEVICE_MAP                          *psSGXDeviceMap;
+
+       if (!psDevInfo)
+       {
+               
+               PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo"));
+               return PVRSRV_OK;
+       }
+
+#if defined(SUPPORT_HW_RECOVERY)
+       if (psDevInfo->hTimer)
+       {
+               eError = OSRemoveTimer(psDevInfo->hTimer);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to remove timer"));
+                       return  eError;
+               }
+               psDevInfo->hTimer = IMG_NULL;
+       }
+#endif 
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+       
+       eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers"));
+               return eError;
+       }
+#endif 
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+       WorkaroundBRN22997Free(psDeviceNode);
+#endif 
+
+       MMU_BIFResetPDFree(psDevInfo);
+
+       
+
+       DeinitDevInfo(psDevInfo);
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+               if (psDevInfo->psResProfMemInfo != IMG_NULL)
+               {
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                         sizeof(PVRSRV_KERNEL_MEM_INFO),
+                                         psDevInfo->psResProfMemInfo,
+                                         0);
+               }
+               psDevInfo->pui32UsedMem = IMG_NULL;
+#endif
+       
+       psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
+       for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++)
+       {
+               switch(psDeviceMemoryHeap[ui32Heap].DevMemHeapType)
+               {
+                       case DEVICE_MEMORY_HEAP_KERNEL:
+                       case DEVICE_MEMORY_HEAP_SHARED:
+                       case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+                       {
+                               if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap != IMG_NULL)
+                               {
+                                       BM_DestroyHeap(psDeviceMemoryHeap[ui32Heap].hDevMemHeap);
+                               }
+                               break;
+                       }
+               }
+       }
+
+       
+       eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX : Failed to destroy kernel context"));
+               return eError;
+       }
+
+       
+       eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+                                                                       (IMG_VOID**)&psSGXDeviceMap);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to get device memory map!"));
+               return eError;
+       }
+
+       
+       if (!psSGXDeviceMap->pvRegsCpuVBase)
+       {
+               
+               if (psDevInfo->pvRegsBaseKM != IMG_NULL)
+               {
+                       OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+                                                        psDevInfo->ui32RegSize,
+                                                        PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                        IMG_NULL);
+               }
+       }
+
+#if defined(SGX_FEATURE_HOST_PORT)
+       if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+       {
+               
+               if (psDevInfo->pvHostPortBaseKM != IMG_NULL)
+               {
+                       OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
+                                                  psDevInfo->ui32HPSize,
+                                                  PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                  IMG_NULL);
+               }
+       }
+#endif 
+
+
+       
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                               sizeof(PVRSRV_SGXDEV_INFO),
+                               psDevInfo,
+                               0);
+
+       psDeviceNode->pvDevice = IMG_NULL;
+
+       if (psDeviceMemoryHeap != IMG_NULL)
+       {
+       
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                               sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+                               psDeviceMemoryHeap,
+                               0);
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO    *psDevInfo,
+                                                                IMG_UINT32                     ui32CoreNum,
+                                                                IMG_CHAR                       *pszName,
+                                                                IMG_UINT32                     ui32RegAddr)
+{
+       IMG_UINT32      ui32RegVal;
+       ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(ui32RegAddr, ui32CoreNum));
+       PVR_LOG(("(P%u) %s%08X", ui32CoreNum, pszName, ui32RegVal));
+}
+
+static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO   *psDevInfo,
+                                                                 IMG_BOOL                              bDumpSGXRegs)
+{
+       IMG_UINT32      ui32CoreNum;
+
+       PVR_LOG(("SGX debug (%s)", PVRVERSION_STRING));
+
+       if (bDumpSGXRegs)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Linear):   0x%08X", (IMG_UINTPTR_T)psDevInfo->pvRegsBaseKM));
+               PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Physical): 0x%08X", psDevInfo->sRegsPhysBase.uiAddr));
+
+               for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT; ui32CoreNum++)
+               {
+               
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS:     ", EUR_CR_EVENT_STATUS);
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS2:    ", EUR_CR_EVENT_STATUS2);
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_CTRL:         ", EUR_CR_BIF_CTRL);
+               #if defined(EUR_CR_BIF_BANK0)
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK0:        ", EUR_CR_BIF_BANK0);
+               #endif
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_INT_STAT:     ", EUR_CR_BIF_INT_STAT);
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_FAULT:        ", EUR_CR_BIF_FAULT);
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_MEM_REQ_STAT: ", EUR_CR_BIF_MEM_REQ_STAT);
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATECTL:       ", EUR_CR_CLKGATECTL);
+               #if defined(EUR_CR_PDS_PC_BASE)
+                       SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_PDS_PC_BASE:      ", EUR_CR_PDS_PC_BASE);
+               #endif
+               }
+       }
+
+       
+
+       QueueDumpDebugInfo();
+
+       {
+               
+
+               IMG_UINT32      *pui32HostCtlBuffer = (IMG_UINT32 *)psDevInfo->psSGXHostCtl;
+               IMG_UINT32      ui32LoopCounter;
+
+               PVR_LOG(("SGX Host control:"));
+
+               for (ui32LoopCounter = 0;
+                        ui32LoopCounter < sizeof(*psDevInfo->psSGXHostCtl) / sizeof(*pui32HostCtlBuffer);
+                        ui32LoopCounter += 4)
+               {
+                       PVR_LOG(("\t(HC-%X) 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32HostCtlBuffer),
+                                       pui32HostCtlBuffer[ui32LoopCounter + 0], pui32HostCtlBuffer[ui32LoopCounter + 1],
+                                       pui32HostCtlBuffer[ui32LoopCounter + 2], pui32HostCtlBuffer[ui32LoopCounter + 3]));
+               }
+       }
+
+       {
+               
+
+               IMG_UINT32      *pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM;
+               IMG_UINT32      ui32LoopCounter;
+
+               PVR_LOG(("SGX TA/3D control:"));
+
+               for (ui32LoopCounter = 0;
+                        ui32LoopCounter < psDevInfo->psKernelSGXTA3DCtlMemInfo->ui32AllocSize / sizeof(*pui32TA3DCtlBuffer);
+                        ui32LoopCounter += 4)
+               {
+                       PVR_LOG(("\t(T3C-%X) 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32TA3DCtlBuffer),
+                                       pui32TA3DCtlBuffer[ui32LoopCounter + 0], pui32TA3DCtlBuffer[ui32LoopCounter + 1],
+                                       pui32TA3DCtlBuffer[ui32LoopCounter + 2], pui32TA3DCtlBuffer[ui32LoopCounter + 3]));
+               }
+       }
+
+       #if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+       {
+               IMG_UINT32      *pui32MKTraceBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+               IMG_UINT32      ui32LastStatusCode, ui32WriteOffset;
+
+               ui32LastStatusCode = *pui32MKTraceBuffer;
+               pui32MKTraceBuffer++;
+               ui32WriteOffset = *pui32MKTraceBuffer;
+               pui32MKTraceBuffer++;
+
+               PVR_LOG(("Last SGX microkernel status code: %08X", ui32LastStatusCode));
+
+               #if defined(PVRSRV_DUMP_MK_TRACE)
+               
+
+               {
+                       IMG_UINT32      ui32LoopCounter;
+
+                       for (ui32LoopCounter = 0;
+                                ui32LoopCounter < SGXMK_TRACE_BUFFER_SIZE;
+                                ui32LoopCounter++)
+                       {
+                               IMG_UINT32      *pui32BufPtr;
+                               pui32BufPtr = pui32MKTraceBuffer +
+                                                               (((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4);
+                               PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X", ui32LoopCounter,
+                                                pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0]));
+                       }
+               }
+               #endif 
+       }
+       #endif 
+
+       {
+               
+
+               PVR_LOG(("SGX Kernel CCB WO:0x%X RO:0x%X",
+                               psDevInfo->psKernelCCBCtl->ui32WriteOffset,
+                               psDevInfo->psKernelCCBCtl->ui32ReadOffset));
+
+               #if defined(PVRSRV_DUMP_KERNEL_CCB)
+               {
+                       IMG_UINT32      ui32LoopCounter;
+
+                       for (ui32LoopCounter = 0;
+                                ui32LoopCounter < sizeof(psDevInfo->psKernelCCB->asCommands) /
+                                                                       sizeof(psDevInfo->psKernelCCB->asCommands[0]);
+                                ui32LoopCounter++)
+                       {
+                               SGXMKIF_COMMAND *psCommand = &psDevInfo->psKernelCCB->asCommands[ui32LoopCounter];
+
+                               PVR_LOG(("\t(KCCB-%X) %08X %08X - %08X %08X %08X %08X", ui32LoopCounter,
+                                               psCommand->ui32ServiceAddress, psCommand->ui32CacheControl,
+                                               psCommand->ui32Data[0], psCommand->ui32Data[1],
+                                               psCommand->ui32Data[2], psCommand->ui32Data[3]));
+                       }
+               }
+               #endif 
+       }
+}
+
+
+#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
+static
+IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                        IMG_UINT32             ui32Component,
+                                                        IMG_UINT32                     ui32CallerID)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+       SGXMKIF_HOST_CTL        *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Component);
+
+       
+
+       eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+       if(eError != PVRSRV_OK)
+       {
+               
+
+
+               PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
+               return;
+       }
+
+       psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+
+       PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
+
+       SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+
+       
+       PDUMPSUSPEND();
+
+       
+#if defined(FIX_HW_BRN_23281)
+
+       for (eError = PVRSRV_ERROR_RETRY; eError == PVRSRV_ERROR_RETRY;)
+#endif
+       {
+       eError = SGXInitialise(psDevInfo, IMG_TRUE);
+       }
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError));
+       }
+
+       
+       PDUMPRESUME();
+
+       PVRSRVPowerUnlock(ui32CallerID);
+
+       
+       SGXScheduleProcessQueuesKM(psDeviceNode);
+
+       
+       
+       PVRSRVProcessQueues(ui32CallerID, IMG_TRUE);
+}
+#endif 
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+IMG_VOID SGXOSTimer(IMG_VOID *pvData)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       static IMG_UINT32       ui32EDMTasks = 0;
+       static IMG_UINT32       ui32LockupCounter = 0; 
+       static IMG_UINT32       ui32NumResets = 0;
+#if defined(FIX_HW_BRN_31093)
+       static IMG_BOOL         bBRN31093Inval = IMG_FALSE;
+#endif
+       IMG_UINT32              ui32CurrentEDMTasks;
+       IMG_BOOL                bLockup = IMG_FALSE;
+       IMG_BOOL                bPoweredDown;
+
+       
+       psDevInfo->ui32TimeStamp++;
+
+#if defined(NO_HARDWARE)
+       bPoweredDown = IMG_TRUE;
+#else
+       bPoweredDown = (SGXIsDevicePowered(psDeviceNode)) ? IMG_FALSE : IMG_TRUE;
+#endif 
+
+       
+       
+       if (bPoweredDown)
+       {
+               ui32LockupCounter = 0;
+       #if defined(FIX_HW_BRN_31093)
+               bBRN31093Inval = IMG_FALSE;
+       #endif
+       }
+       else
+       {
+               
+               ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0);
+               if (psDevInfo->ui32EDMTaskReg1 != 0)
+               {
+                       ui32CurrentEDMTasks ^= OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg1);
+               }
+               if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
+                       (psDevInfo->ui32NumResets == ui32NumResets))
+               {
+                       ui32LockupCounter++;
+                       if (ui32LockupCounter == 3)
+                       {
+                               ui32LockupCounter = 0;
+
+       #if defined(FIX_HW_BRN_31093)
+                               if (bBRN31093Inval == IMG_FALSE)
+                               {
+
+               #if defined(FIX_HW_BRN_29997)
+                                       IMG_UINT32      ui32BIFCtrl;
+
+                                       ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+                                       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_PAUSE_MASK);
+
+                                       OSWaitus(200 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+               #endif
+
+                                       bBRN31093Inval = IMG_TRUE;
+
+                                       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK);
+
+                                       OSWaitus(200 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+
+               #if defined(FIX_HW_BRN_29997)
+
+                                       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+               #endif
+                               }
+                               else
+       #endif
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks));
+
+                                       bLockup = IMG_TRUE;
+                               }
+                       }
+               }
+               else
+               {
+       #if defined(FIX_HW_BRN_31093)
+                       bBRN31093Inval = IMG_FALSE;
+       #endif
+                       ui32LockupCounter = 0;
+                       ui32EDMTasks = ui32CurrentEDMTasks;
+                       ui32NumResets = psDevInfo->ui32NumResets;
+               }
+       }
+
+       if (bLockup)
+       {
+               SGXMKIF_HOST_CTL        *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+               
+               psSGXHostCtl->ui32HostDetectedLockups ++;
+
+               
+               HWRecoveryResetSGX(psDeviceNode, 0, KERNEL_ID);
+       }
+}
+#endif 
+
+
+#if defined(SYS_USING_INTERRUPTS)
+
+IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
+{
+       IMG_BOOL bInterruptProcessed = IMG_FALSE;
+
+
+       
+       {
+               IMG_UINT32 ui32EventStatus, ui32EventEnable;
+               IMG_UINT32 ui32EventClear = 0;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+               IMG_UINT32 ui32EventStatus2, ui32EventEnable2;
+#endif         
+               IMG_UINT32 ui32EventClear2 = 0;
+               PVRSRV_DEVICE_NODE *psDeviceNode;
+               PVRSRV_SGXDEV_INFO *psDevInfo;
+
+               
+               if(pvData == IMG_NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n"));
+                       return bInterruptProcessed;
+               }
+
+               psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+               psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+               ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+               ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE);
+
+               
+               ui32EventStatus &= ui32EventEnable;
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+               ui32EventStatus2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+               ui32EventEnable2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE2);
+
+               
+               ui32EventStatus2 &= ui32EventEnable2;
+#endif 
+
+               
+
+               if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
+               {
+                       ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
+               }
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+               if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK)
+               {
+                       ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK;
+               }
+
+               if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK)
+               {
+                       ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK;
+               }
+#endif 
+
+               if (ui32EventClear || ui32EventClear2)
+               {
+                       bInterruptProcessed = IMG_TRUE;
+
+                       
+                       ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
+
+                       
+                       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
+                       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32EventClear2);
+               }
+       }
+
+       return bInterruptProcessed;
+}
+
+
+static IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
+{
+       PVRSRV_DEVICE_NODE      *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+       SGXMKIF_HOST_CTL        *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+       if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) != 0UL) &&
+               ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) == 0UL))
+       {
+               HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+       }
+
+#if defined(OS_SUPPORTS_IN_LISR)
+       if (psDeviceNode->bReProcessDeviceCommandComplete)
+       {
+               SGXScheduleProcessQueuesKM(psDeviceNode);
+       }
+#endif
+
+       SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
+
+       pvr_trcmd_check_syn_completions(PVR_TRCMD_SGX_COMP);
+}
+#endif 
+
+
+
+#if defined(SUPPORT_MEMORY_TILING)
+PVRSRV_ERROR SGX_AllocMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                               PVRSRV_KERNEL_MEM_INFO  *psMemInfo,
+                                                                               IMG_UINT32 ui32TilingStride,
+                                                                               IMG_UINT32 *pui32RangeIndex)
+{
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       IMG_UINT32 i;
+       IMG_UINT32 ui32Start;
+       IMG_UINT32 ui32End;
+       IMG_UINT32 ui32Offset;
+       IMG_UINT32 ui32Val;
+
+       
+       for(i=0; i<10; i++)
+       {
+               if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0)
+               {
+                       
+                       psDevInfo->ui32MemTilingUsage |= 1U << i;
+                       
+                       *pui32RangeIndex = i;
+                       goto RangeAllocated;
+               }
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use"));
+       return PVRSRV_ERROR_EXCEEDED_HW_LIMITS;
+
+RangeAllocated:
+       ui32Offset = EUR_CR_BIF_TILE0 + (i<<2);
+
+       ui32Start = psMemInfo->sDevVAddr.uiAddr;
+       ui32End = ui32Start + psMemInfo->ui32AllocSize + SGX_MMU_PAGE_SIZE - 1;
+
+       ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK)
+                       | (((ui32End>>20) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK)
+                       | (((ui32Start>>20) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK)
+                       | (0x8 << EUR_CR_BIF_TILE0_CFG_SHIFT);
+
+       
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+       PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+       ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2);
+
+       ui32Val = (((ui32End>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK)
+                       | (((ui32Start>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK);
+
+       
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+       PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+       return PVRSRV_OK;
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+       PVR_UNREFERENCED_PARAMETER(psMemInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32TilingStride);
+       PVR_UNREFERENCED_PARAMETER(pui32RangeIndex);
+
+       PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: device does not support memory tiling"));
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                               IMG_UINT32 ui32RangeIndex)
+{
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       IMG_UINT32 ui32Offset;
+       IMG_UINT32 ui32Val;
+
+       if(ui32RangeIndex >= 10)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: invalid Range index "));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       
+       psDevInfo->ui32MemTilingUsage &= ~(1<<ui32RangeIndex);
+
+       
+       ui32Offset = EUR_CR_BIF_TILE0 + (ui32RangeIndex<<2);
+       ui32Val = 0;
+
+       
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+       PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+       return PVRSRV_OK;
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+       PVR_UNREFERENCED_PARAMETER(ui32RangeIndex);
+
+       PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: device does not support memory tiling"));
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+}
+#endif
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+static
+PVRSRV_ERROR SGXAccumlateMapRes(PRESMAN_ITEM psRes, va_list va)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = IMG_NULL;
+       IMG_UINT32 *pui32UsedPrivateMem = IMG_NULL, *pui32UsedSharedMem = IMG_NULL;
+       PVRSRV_KERNEL_MEM_INFO  *psMemInfo;
+       BM_BUF  *psBuf;
+       psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+       pui32UsedPrivateMem = va_arg(va, IMG_UINT32*);
+       pui32UsedSharedMem = va_arg(va, IMG_UINT32*);
+       if (!psDeviceNode || !pui32UsedPrivateMem || !pui32UsedSharedMem) {
+               PVR_LOG(("DBGRESPROF:wrong prarmeter\n"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       /*if (psRes->ui32ResType != RESMAN_TYPE_DEVICEMEM_MAPPING)
+               PVR_LOG(("DBGRESPROF:wrong resource type\n"));*/
+
+       psMemInfo = PVRSRVGetMapMemInfo(PVRSRVGetResData(psRes));
+       psBuf = psMemInfo->sMemBlk.hBuffer;
+       if (psDeviceNode == psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode)
+       {
+               *pui32UsedSharedMem += psMemInfo->ui32AllocSize;
+               if (psMemInfo->psKernelSyncInfo)
+                       *pui32UsedSharedMem += psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize;
+       }
+       return PVRSRV_OK;
+}
+static
+PVRSRV_ERROR SGXAccumlateAllocRes(PRESMAN_ITEM psRes, va_list va)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = IMG_NULL;
+       IMG_UINT32 *pui32UsedPrivateMem = IMG_NULL, *pui32UsedExportedMem = IMG_NULL;
+       PVRSRV_KERNEL_MEM_INFO  *psMemInfo;
+       BM_BUF  *psBuf;
+       psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+       pui32UsedPrivateMem = va_arg(va, IMG_UINT32*);
+       pui32UsedExportedMem = va_arg(va, IMG_UINT32*);
+       if (!psDeviceNode || !pui32UsedPrivateMem || !pui32UsedExportedMem) {
+               PVR_LOG(("DBGRESPROF:wrong prarmeter\n"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       /*if (psRes->ui32ResType != RESMAN_TYPE_DEVICEMEM_ALLOCATION)
+               PVR_LOG(("DBGRESPROF:wrong resource type\n"));*/
+
+       psMemInfo = PVRSRVGetResData(psRes);
+       psBuf = psMemInfo->sMemBlk.hBuffer;
+       if (psDeviceNode == psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode)
+       {
+               if (psBuf->ui32ExportCount)
+               {
+                       *pui32UsedExportedMem += psMemInfo->ui32AllocSize;
+                       if (psMemInfo->psKernelSyncInfo)
+                               *pui32UsedExportedMem += psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize;
+               }
+               else
+               {
+                       *pui32UsedPrivateMem += psMemInfo->ui32AllocSize;
+                       if (psMemInfo->psKernelSyncInfo)
+                               *pui32UsedPrivateMem += psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static
+IMG_VOID SGXAccumlateUsedMem(PVRSRV_PER_PROCESS_DATA* psProc, va_list va)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       SGX_MISC_INFO *psMiscInfo;
+       IMG_UINT32 ui32UsedPrivateMem = 0, ui32UsedSharedMem = 0, ui32UsedExportedMem = 0;
+       PVRSRV_SGX_RESOURCE_INFO *psSGXResInfo;
+       psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+       psMiscInfo = va_arg(va, SGX_MISC_INFO*);
+       psSGXResInfo = &psMiscInfo->uData.sSGXResourceInfo;
+
+       PVRSRVResManAnyByCriteria(psProc->hResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0,
+                                       0, &SGXAccumlateAllocRes, psDeviceNode, &ui32UsedPrivateMem, &ui32UsedExportedMem);
+       PVRSRVResManAnyByCriteria(psProc->hResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0,
+                                       0, &SGXAccumlateMapRes, psDeviceNode, &ui32UsedPrivateMem, &ui32UsedSharedMem);
+       psSGXResInfo->ui32UsedMem += ui32UsedPrivateMem;
+       psSGXResInfo->ui32UsedMem += ui32UsedExportedMem;
+       /*PVR_LOG(("MarkTu ID:%d, used:%d, shared:%d\n", psProc->ui32PID, ui32UsedPrivateMem, ui32UsedSharedMem));*/
+       if ((psMiscInfo->eRequest == SGX_MISC_INFO_RESOURCEPROF_GLOBAL) &&
+               (ui32UsedPrivateMem || ui32UsedSharedMem) &&
+               (psSGXResInfo->ui32ProcCnt < MAX_PROC))
+       {
+               psSGXResInfo->aui32ProcMem[psSGXResInfo->ui32ProcCnt][0] = psProc->ui32PID;
+               psSGXResInfo->aui32ProcMem[psSGXResInfo->ui32ProcCnt][1] = ui32UsedPrivateMem;
+               psSGXResInfo->aui32ProcMem[psSGXResInfo->ui32ProcCnt][2] = ui32UsedExportedMem + ui32UsedSharedMem;
+               psSGXResInfo->ui32ProcCnt++;
+       }
+       if(psSGXResInfo->ui32ProcCnt >= MAX_PROC)
+               PVR_LOG(("DBGRESPROF:Maxiam process number exceed\n"));
+
+}
+static
+PVRSRV_ERROR SGXGetResourceProfile(SGX_MISC_INFO *psMiscInfo, PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_MEM_INFO sMemInfo;
+       IMG_UINT32 ui32FreeMem;
+       PVRSRV_PER_PROCESS_DATA* psPerProcList;
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       if (!psMiscInfo || !psDeviceNode)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       OSGetMemoryInfo(&sMemInfo);
+       ui32FreeMem = sMemInfo.ui32FreeMem / 2;
+       OSMemSet(&psMiscInfo->uData.sSGXResourceInfo, 0,sizeof(psMiscInfo->uData.sSGXResourceInfo));
+       psPerProcList = PVRSRVPerProcessList();
+       List_PVRSRV_PER_PROCESS_DATA_ForEach_va(psPerProcList,
+                                               &SGXAccumlateUsedMem,
+                                               psDeviceNode,
+                                               psMiscInfo);
+       if(psMiscInfo->uData.sSGXResourceInfo.ui32UsedMem != *psDevInfo->pui32UsedMem)
+       {
+               PVR_LOG(("Usedmem:cal:%d;stat:%d\n", psMiscInfo->uData.sSGXResourceInfo.ui32UsedMem,
+                       *psDevInfo->pui32UsedMem));
+       }
+       psMiscInfo->uData.sSGXResourceInfo.ui32TotalMem = ui32FreeMem + psMiscInfo->uData.sSGXResourceInfo.ui32UsedMem;
+
+       return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR SGXGetResProfMemInfo(SGX_MISC_INFO *psMiscInfo, PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_CLIENT_MEM_INFO                  *psSGXResProfMemInfo;
+       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = ((PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice)->psResProfMemInfo;
+       psSGXResProfMemInfo = &psMiscInfo->uData.sSGXResProfMemInfo;
+       OSMemSet(psSGXResProfMemInfo,
+                        0,
+                        sizeof(*psSGXResProfMemInfo));
+
+       psSGXResProfMemInfo->pvLinAddrKM =
+                       psKernelMemInfo->pvLinAddrKM;
+
+       psSGXResProfMemInfo->pvLinAddr = 0;
+       psSGXResProfMemInfo->ui32Flags =
+               psKernelMemInfo->ui32Flags;
+       psSGXResProfMemInfo->ui32AllocSize =
+               psKernelMemInfo->ui32AllocSize;
+       psSGXResProfMemInfo->hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR SGXResProfiling(IMG_VOID *pvDeviceNode, IMG_UINT32 ui32AllocedMem, IMG_BOOL bAlloc)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*)pvDeviceNode;
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       SYS_DATA* psSysData = IMG_NULL;
+       IMG_HANDLE hOSEventKM;
+
+       if (!psDevInfo || psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
+       {
+               PVR_LOG(("SGXResProfiling:invalid psDevInfo or invaid device type"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       if(bAlloc)
+       {
+               *psDevInfo->pui32UsedMem += ui32AllocedMem;
+       }
+       else
+       {
+               *psDevInfo->pui32UsedMem -= ui32AllocedMem;
+       }
+       SysAcquireData(&psSysData);
+       if (psSysData->psGlobalEventObject)
+       {
+               hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+               if(hOSEventKM)
+               {
+                       OSEventObjectSignal(hOSEventKM);
+               }
+       }
+       return PVRSRV_OK;
+}
+
+#endif
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       DEVICE_MEMORY_INFO *psDevMemoryInfo;
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+       
+       psDeviceNode->sDevId.eDeviceType                = DEV_DEVICE_TYPE;
+       psDeviceNode->sDevId.eDeviceClass               = DEV_DEVICE_CLASS;
+#if defined(PDUMP)
+       {
+               
+               SGX_DEVICE_MAP *psSGXDeviceMemMap;
+               SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+                                                         (IMG_VOID**)&psSGXDeviceMemMap);
+
+               psDeviceNode->sDevId.pszPDumpDevName = psSGXDeviceMemMap->pszPDumpDevName;
+               PVR_ASSERT(psDeviceNode->sDevId.pszPDumpDevName != IMG_NULL);
+       }
+       
+       psDeviceNode->sDevId.pszPDumpRegName    = SGX_PDUMPREG_NAME;
+#endif 
+
+       psDeviceNode->pfnInitDevice             = &DevInitSGXPart1;
+       psDeviceNode->pfnDeInitDevice   = &DevDeInitSGX;
+
+       psDeviceNode->pfnInitDeviceCompatCheck  = &SGXDevInitCompatCheck;
+#if defined(PDUMP)
+       psDeviceNode->pfnPDumpInitDevice = &SGXResetPDump;
+       psDeviceNode->pfnMMUGetContextID = &MMU_GetPDumpContextID;
+#endif
+       
+
+       psDeviceNode->pfnMMUInitialise = &MMU_Initialise;
+       psDeviceNode->pfnMMUFinalise = &MMU_Finalise;
+       psDeviceNode->pfnMMUInsertHeap = &MMU_InsertHeap;
+       psDeviceNode->pfnMMUCreate = &MMU_Create;
+       psDeviceNode->pfnMMUDelete = &MMU_Delete;
+       psDeviceNode->pfnMMUAlloc = &MMU_Alloc;
+       psDeviceNode->pfnMMUFree = &MMU_Free;
+       psDeviceNode->pfnMMUMapPages = &MMU_MapPages;
+       psDeviceNode->pfnMMUMapShadow = &MMU_MapShadow;
+       psDeviceNode->pfnMMUUnmapPages = &MMU_UnmapPages;
+       psDeviceNode->pfnMMUMapScatter = &MMU_MapScatter;
+       psDeviceNode->pfnMMUGetPhysPageAddr = &MMU_GetPhysPageAddr;
+       psDeviceNode->pfnMMUGetPDDevPAddr = &MMU_GetPDDevPAddr;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+       psDeviceNode->pfnMMUIsHeapShared = &MMU_IsHeapShared;
+#endif
+
+#if defined (SYS_USING_INTERRUPTS)
+       
+
+       psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
+       psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+       psDeviceNode->pfnAllocMemTilingRange = SGX_AllocMemTilingRange;
+       psDeviceNode->pfnFreeMemTilingRange = SGX_FreeMemTilingRange;
+#endif
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       psDeviceNode->pfnResProfCB = &SGXResProfiling;
+#endif
+
+       psDeviceNode->pfnDeviceCommandComplete = &SGXCommandComplete;
+
+       
+
+       psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+       
+       psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE;
+
+       
+       psDevMemoryInfo->ui32Flags = 0;
+
+       
+       if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+                                        sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+                                        (IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0,
+                                        "Array of Device Memory Heap Info") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO"));
+               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+       }
+       OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0, sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID);
+
+       psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+       
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                               | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap->pszName = "General";
+       psDeviceMemoryHeap->pszBSName = "General BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+       
+       psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+#endif
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                               | PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap->pszName = "TA Data";
+       psDeviceMemoryHeap->pszBSName = "TA Data BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                                       | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                                       | PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap->pszName = "Kernel Code";
+       psDeviceMemoryHeap->pszBSName = "Kernel Code BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                                               | PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap->pszName = "KernelData";
+       psDeviceMemoryHeap->pszBSName = "KernelData BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE;
+       
+
+
+
+
+
+       psDeviceMemoryHeap->ui32HeapSize = ((10 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
+       PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_PIXELSHADER_HEAP_SIZE);
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                                               | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap->pszName = "PixelShaderUSSE";
+       psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE;
+       
+       psDeviceMemoryHeap->ui32HeapSize = ((4 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
+       PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_VERTEXSHADER_HEAP_SIZE);
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                                               | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap->pszName = "VertexShaderUSSE";
+       psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                                               | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap->pszName = "PDSPixelCodeData";
+       psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                                               | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap->pszName = "PDSVertexCodeData";
+       psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                               | PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap->pszName = "CacheCoherent";
+       psDeviceMemoryHeap->pszBSName = "CacheCoherent BS";
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       
+       psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+       psDeviceMemoryHeap++;
+
+
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_3DPARAMETERS_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_3DPARAMETERS_HEAP_SIZE;
+       psDeviceMemoryHeap->pszName = "3DParameters";
+       psDeviceMemoryHeap->pszBSName = "3DParameters BS";
+#if defined(SUPPORT_PERCONTEXT_PB)
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                                       | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                                       | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+#else
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                       | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                       | PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+#endif
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap->pszName = "GeneralMapping";
+       psDeviceMemoryHeap->pszBSName = "GeneralMapping BS";
+       #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410)
+       
+
+
+
+
+
+
+               psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+       #else 
+               psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+       #endif 
+
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       
+       psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+       psDeviceMemoryHeap++;
+#endif 
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                               | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap->pszName = "2D";
+       psDeviceMemoryHeap->pszBSName = "2D BS";
+       
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+#endif 
+
+
+#if defined(FIX_HW_BRN_26915)
+       
+       
+       psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_CGBUFFER_HEAP_ID);
+       psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_CGBUFFER_HEAP_BASE;
+       psDeviceMemoryHeap->ui32HeapSize = SGX_CGBUFFER_HEAP_SIZE;
+       psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+                                                                                                               | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+                                                                                                               | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap->pszName = "CGBuffer";
+       psDeviceMemoryHeap->pszBSName = "CGBuffer BS";
+
+       psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+       
+       psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+       psDeviceMemoryHeap++;
+#endif 
+
+       
+       psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+
+       return PVRSRV_OK;
+}
+
+#if defined(PDUMP)
+static
+PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)(psDeviceNode->pvDevice);
+       psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
+       PVR_DPF((PVR_DBG_MESSAGE, "Reset pdump CCB write offset."));
+       
+       return PVRSRV_OK;
+}
+#endif 
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE                                     hDevCookie,
+                                                               SGX_CLIENT_INFO*                psClientInfo)
+{
+       PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+       
+
+       psDevInfo->ui32ClientRefCount++;
+
+       
+
+       psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+       
+
+       OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData));
+
+       
+       return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO   *psDevInfo)
+{
+       PVR_LOG(("SGX panic"));
+       SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+       OSPanic();
+}
+
+static int fw_version_supported(const int fw_ver[4])
+{
+       static const int sup_versions[][4] = {
+               { 1, 6, 16, 4120 },
+               { 1, 6, 16, 4043 },
+       };
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(sup_versions); i++)
+               if (!memcmp(fw_ver, sup_versions[i], sizeof(fw_ver)))
+                       return 1;
+
+       return 0;
+}
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR    eError;
+       PVRSRV_SGXDEV_INFO                              *psDevInfo;
+       unsigned long                   build_options;
+       unsigned long                   fw_ver_packed;
+       int                             fw_ver[4];
+#if !defined(NO_HARDWARE)
+       PPVRSRV_KERNEL_MEM_INFO                 psMemInfo;
+       PVRSRV_SGX_MISCINFO_INFO                *psSGXMiscInfoInt;      
+       PVRSRV_SGX_MISCINFO_FEATURES    *psSGXFeatures;
+       SGX_MISCINFO_STRUCT_SIZES               *psSGXStructSizes;      
+       IMG_BOOL                                                bStructSizesFailed;
+
+       
+       IMG_BOOL        bCheckCoreRev;
+       const IMG_UINT32 aui32CoreRevExceptions[] =
+       {
+               0x10100, 0x10101
+       };
+       const IMG_UINT32        ui32NumCoreExceptions = sizeof(aui32CoreRevExceptions) / (2*sizeof(IMG_UINT32));
+       IMG_UINT        i;
+#endif
+
+       
+       if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
+       {
+               PVR_LOG(("(FAIL) SGXInit: Device not of type SGX"));
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto chk_exit;
+       }
+
+
+       psDevInfo = psDeviceNode->pvDevice;
+       build_options = psDevInfo->ui32ClientBuildOptions &
+                                       SGX_BUILD_OPTION_MASK;
+
+       if (build_options != SGX_BUILD_OPTIONS) {
+               pr_err("pvr: user compile option mismatch (kernel:%#08lx, user:%#08lx)\n",
+                       (unsigned long)SGX_BUILD_OPTIONS, build_options);
+               eError = PVRSRV_ERROR_BUILD_MISMATCH;
+
+               goto chk_exit;
+       } else {
+               pr_debug("pvr: user compile options ok\n");
+       }
+
+#if !defined (NO_HARDWARE)
+       psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+       
+       psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+       psSGXMiscInfoInt->ui32MiscInfoFlags = 0;
+       psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
+       eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+
+       if (eError != PVRSRV_OK) {
+               pr_err("pvr: can't retrieve the firmware version\n");
+               goto chk_exit;
+       }
+
+       psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+       fw_ver_packed = psSGXFeatures->ui32DDKVersion;
+
+       fw_ver[0] = PVR_FW_VER_MAJOR(fw_ver_packed);
+       fw_ver[1] = PVR_FW_VER_MINOR(fw_ver_packed);
+       fw_ver[2] = PVR_FW_VER_BRANCH(fw_ver_packed);
+       fw_ver[3] = psSGXFeatures->ui32DDKBuild;
+
+       if (!fw_version_supported(fw_ver)) {
+               pr_err("pvr: unsupported firmware version (%d.%d.%d.%d)\n",
+                       fw_ver[0], fw_ver[1], fw_ver[2], fw_ver[3]);
+               eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+               PVR_DBG_BREAK;
+
+               goto chk_exit;
+       } else {
+               pr_debug("pvr: firmware version ok (%d.%d.%d.%d)\n",
+                       fw_ver[0], fw_ver[1], fw_ver[2], fw_ver[3]);
+       }
+
+       
+       if (psSGXFeatures->ui32CoreRevSW == 0)
+       {
+               
+
+               PVR_LOG(("SGXInit: HW core rev (%x) check skipped.",
+                               psSGXFeatures->ui32CoreRev));
+       }
+       else
+       {
+               
+               bCheckCoreRev = IMG_TRUE;
+               for(i=0; i<ui32NumCoreExceptions; i+=2)
+               {
+                       if( (psSGXFeatures->ui32CoreRev==aui32CoreRevExceptions[i]) &&
+                               (psSGXFeatures->ui32CoreRevSW==aui32CoreRevExceptions[i+1])     )
+                       {
+                               PVR_LOG(("SGXInit: HW core rev (%x), SW core rev (%x) check skipped.",
+                                               psSGXFeatures->ui32CoreRev,
+                                               psSGXFeatures->ui32CoreRevSW));
+                               bCheckCoreRev = IMG_FALSE;
+                       }
+               }
+
+               if (bCheckCoreRev)
+               {
+                       if (psSGXFeatures->ui32CoreRev != psSGXFeatures->ui32CoreRevSW)
+                       {
+                               PVR_LOG(("(FAIL) SGXInit: Incompatible HW core rev (%x) and SW core rev (%x).",
+                                               psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+                                               eError = PVRSRV_ERROR_BUILD_MISMATCH;
+                                               goto chk_exit;
+                       }
+                       else
+                       {
+                               PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: HW core rev (%x) and SW core rev (%x) match. [ OK ]",
+                                               psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+                       }
+               }
+       }
+
+       
+       psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes;
+
+       bStructSizesFailed = IMG_FALSE;
+
+       CHECK_SIZE(HOST_CTL);
+       CHECK_SIZE(COMMAND);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+       CHECK_SIZE(2DCMD);
+       CHECK_SIZE(2DCMD_SHARED);
+#endif
+       CHECK_SIZE(CMDTA);
+       CHECK_SIZE(CMDTA_SHARED);
+       CHECK_SIZE(TRANSFERCMD);
+       CHECK_SIZE(TRANSFERCMD_SHARED);
+
+       CHECK_SIZE(3DREGISTERS);
+       CHECK_SIZE(HWPBDESC);
+       CHECK_SIZE(HWRENDERCONTEXT);
+       CHECK_SIZE(HWRENDERDETAILS);
+       CHECK_SIZE(HWRTDATA);
+       CHECK_SIZE(HWRTDATASET);
+       CHECK_SIZE(HWTRANSFERCONTEXT);
+
+       if (bStructSizesFailed == IMG_TRUE)
+       {
+               PVR_LOG(("(FAIL) SGXInit: Mismatch in SGXMKIF structure sizes."));
+               eError = PVRSRV_ERROR_BUILD_MISMATCH;
+               goto chk_exit;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]"));
+       }
+
+       
+       build_options = psSGXFeatures->ui32BuildOptions & SGX_BUILD_OPTION_MASK;
+       if (build_options != SGX_BUILD_OPTIONS) {
+               pr_err("pvr: firwmare compile option mismatch (kernel:%#08lx, firmware:%#08lx)\n",
+                       (unsigned long)SGX_BUILD_OPTIONS, build_options);
+               eError = PVRSRV_ERROR_BUILD_MISMATCH;
+
+               goto chk_exit;
+       } else {
+               pr_debug("pvr: firwmare build options match\n");
+       }
+#endif 
+
+       eError = PVRSRV_OK;
+chk_exit:
+#if defined(IGNORE_SGX_INIT_COMPATIBILITY_CHECK)
+       return PVRSRV_OK;
+#else
+       return eError;
+#endif
+}
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO  *psDevInfo,
+                                                                  PVRSRV_DEVICE_NODE   *psDeviceNode)
+{
+       PVRSRV_ERROR            eError;
+       SGXMKIF_COMMAND         sCommandData;  
+       PVRSRV_SGX_MISCINFO_INFO                        *psSGXMiscInfoInt;      
+       PVRSRV_SGX_MISCINFO_FEATURES            *psSGXFeatures;         
+       SGX_MISCINFO_STRUCT_SIZES                       *psSGXStructSizes;      
+
+       PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+       if (! psMemInfo->pvLinAddrKM)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Invalid address."));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+       psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
+       psSGXStructSizes = &psSGXMiscInfoInt->sSGXStructSizes;
+
+       psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
+
+       
+       OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
+       OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes));
+
+       
+       sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr; 
+
+       PDUMPCOMMENT("Microkernel kick for SGXGetMiscInfo");
+       eError = SGXScheduleCCBCommandKM(psDeviceNode,
+                                                                        SGXMKIF_CMD_GETMISCINFO,
+                                                                        &sCommandData,
+                                                                        KERNEL_ID,
+                                                                        0);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: SGXScheduleCCBCommandKM failed."));
+               return eError;
+       }
+
+       
+#if !defined(NO_HARDWARE)
+       {
+               IMG_BOOL bExit;
+
+               bExit = IMG_FALSE;
+               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+               {
+                       if ((psSGXMiscInfoInt->ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) != 0)
+                       {
+                               bExit = IMG_TRUE;
+                               break;
+                       }
+               } END_LOOP_UNTIL_TIMEOUT();
+
+               
+               if (!bExit)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info."));
+                       return PVRSRV_ERROR_TIMEOUT;
+               }
+       }
+#endif 
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO       *psDevInfo,
+                                                         SGX_MISC_INFO                 *psMiscInfo,
+                                                         PVRSRV_DEVICE_NODE    *psDeviceNode,
+                                                         IMG_HANDLE                     hDevMemContext)
+{
+       PVRSRV_ERROR eError;
+       PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+       IMG_UINT32      *pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags;
+
+       
+       *pui32MiscInfoFlags = 0;
+
+#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+       PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+#endif
+
+       switch(psMiscInfo->eRequest)
+       {
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+               case SGX_MISC_INFO_REQUEST_SET_BREAKPOINT:
+               {
+                       IMG_UINT32      ui32MaskDM;
+                       IMG_UINT32      ui32CtrlWEnable;
+                       IMG_UINT32      ui32CtrlREnable;
+                       IMG_UINT32      ui32CtrlTrapEnable;
+                       IMG_UINT32              ui32RegVal;
+                       IMG_UINT32              ui32StartRegVal;
+                       IMG_UINT32              ui32EndRegVal;
+                       SGXMKIF_COMMAND sCommandData;
+
+                       
+                       if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable)
+                       {
+                               
+                               IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr;
+                               IMG_DEV_VIRTADDR sBPDevVAddrEnd = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddrEnd;
+
+                               
+                               ui32StartRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_START_ADDRESS_MASK;
+                               ui32EndRegVal = sBPDevVAddrEnd.uiAddr & EUR_CR_BREAKPOINT0_END_ADDRESS_MASK;
+
+                               ui32MaskDM = psMiscInfo->uData.sSGXBreakpointInfo.ui32DataMasterMask;
+                               ui32CtrlWEnable = psMiscInfo->uData.sSGXBreakpointInfo.bWrite;
+                               ui32CtrlREnable = psMiscInfo->uData.sSGXBreakpointInfo.bRead;
+                               ui32CtrlTrapEnable = psMiscInfo->uData.sSGXBreakpointInfo.bTrapped;
+
+                               
+                               ui32RegVal = ((ui32MaskDM<<EUR_CR_BREAKPOINT0_MASK_DM_SHIFT) & EUR_CR_BREAKPOINT0_MASK_DM_MASK) |
+                                                        ((ui32CtrlWEnable<<EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK) |
+                                                        ((ui32CtrlREnable<<EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK) |
+                                                        ((ui32CtrlTrapEnable<<EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK);
+                       }
+                       else
+                       {
+                               
+                               ui32RegVal = ui32StartRegVal = ui32EndRegVal = 0;
+                       }
+
+                       
+                       sCommandData.ui32Data[0] = psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex;
+                       sCommandData.ui32Data[1] = ui32StartRegVal;
+                       sCommandData.ui32Data[2] = ui32EndRegVal;
+                       sCommandData.ui32Data[3] = ui32RegVal;
+
+                       
+                       psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+
+                       PDUMPCOMMENT("Microkernel kick for setting a data breakpoint");
+                       eError = SGXScheduleCCBCommandKM(psDeviceNode,
+                                                                                        SGXMKIF_CMD_DATABREAKPOINT,
+                                                                                        &sCommandData,
+                                                                                        KERNEL_ID,
+                                                                                        0);
+
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed."));
+                               return eError;
+                       }
+
+#if defined(NO_HARDWARE)
+                       
+                       psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+#else
+                       {
+                               IMG_BOOL bExit;
+
+                               bExit = IMG_FALSE;
+                               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+                               {
+                                       if (psDevInfo->psSGXHostCtl->ui32BPSetClearSignal != 0)
+                                       {
+                                               bExit = IMG_TRUE;
+                                               
+                                               psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+                                               break;
+                                       }
+                               } END_LOOP_UNTIL_TIMEOUT();
+
+                               
+                               if (!bExit)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: Timeout occurred waiting BP set/clear"));
+                                       return PVRSRV_ERROR_TIMEOUT;
+                               }
+                       }
+#endif 
+
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_REQUEST_WAIT_FOR_BREAKPOINT:
+               {
+                       
+                       
+                       PDUMPCOMMENT("Wait for data breakpoint hit");
+
+#if defined(NO_HARDWARE) && defined(PDUMP)
+                       {
+                               PDUMPREGPOL(SGX_PDUMPREG_NAME,
+                                                       EUR_CR_EVENT_STATUS2,
+                                                       EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK,
+                                                       EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK);
+
+                               PDUMPREG(SGX_PDUMPREG_NAME,
+                                                EUR_CR_EVENT_HOST_CLEAR2,
+                                                EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK);
+
+                               PDUMPCOMMENT("Breakpoint detected.  Wait a bit to show that pipeline stops in simulation");
+                               PDUMPIDL(2000);
+
+                               PDUMPCOMMENT("Now we can resume");
+                               PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BREAKPOINT_TRAP, EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK);
+                       }
+#else
+                       {
+                               
+                       }
+#endif 
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT:
+               {
+                       
+
+
+
+
+                       
+
+#if !defined(NO_HARDWARE)
+                       IMG_BOOL bTrappedBPMaster;
+                       IMG_BOOL abTrappedBPPerCore[SGX_FEATURE_MP_CORE_COUNT];
+                       IMG_UINT32 ui32CoreNum, ui32TrappedBPCoreNum;
+                       IMG_BOOL bTrappedBPAny;
+
+                       ui32TrappedBPCoreNum = 0;
+                       bTrappedBPMaster = !!(EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT));
+                       bTrappedBPAny = bTrappedBPMaster;
+                       for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT; ui32CoreNum++)
+                       {
+                               abTrappedBPPerCore[ui32CoreNum] = !!(EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum)));
+                               if (abTrappedBPPerCore[ui32CoreNum])
+                               {
+                                       bTrappedBPAny = IMG_TRUE;
+                                       ui32TrappedBPCoreNum = ui32CoreNum;
+                               }
+                       }
+
+                       psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny;
+
+                       if (psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP)
+                       {
+                               IMG_UINT32 ui32Info0, ui32Info1;
+
+                               ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum));
+                               ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum));
+
+                               psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
+                               psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK;
+                               psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT;
+                               psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_MASK);
+                               psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
+                               psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
+                               psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum;
+                       }
+#endif 
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT:
+               {
+                       
+                       
+                       
+#if !defined(NO_HARDWARE)
+                       IMG_UINT32 ui32CoreNum;
+                       IMG_BOOL bMaster;
+                       IMG_UINT32 ui32OldSeqNum, ui32NewSeqNum;
+
+                       ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum;
+                       bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT;
+                       if (bMaster)
+                       {
+                               
+                               
+                               ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
+                               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT_TRAP, EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK);
+                               do
+                               {
+                                       ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
+                               }
+                               while (ui32OldSeqNum == ui32NewSeqNum);
+                       }
+                       else
+                       {
+                               
+                               ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
+                               OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP, ui32CoreNum), EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK);
+                               do
+                               {
+                                       ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
+                               }
+                               while (ui32OldSeqNum == ui32NewSeqNum);
+                       }
+#endif 
+                       return PVRSRV_OK;
+               }
+#endif 
+
+               case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
+               {
+                       psMiscInfo->uData.ui32SGXClockSpeed = psDevInfo->ui32CoreClockSpeed;
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_REQUEST_ACTIVEPOWER:
+               {
+                       psMiscInfo->uData.sActivePower.ui32NumActivePowerEvents = psDevInfo->psSGXHostCtl->ui32NumActivePowerEvents;
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_REQUEST_LOCKUPS:
+               {
+#if defined(SUPPORT_HW_RECOVERY)
+                       psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = psDevInfo->psSGXHostCtl->ui32uKernelDetectedLockups;
+                       psMiscInfo->uData.sLockups.ui32HostDetectedLockups = psDevInfo->psSGXHostCtl->ui32HostDetectedLockups;
+#else
+                       psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = 0;
+                       psMiscInfo->uData.sLockups.ui32HostDetectedLockups = 0;
+#endif
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_REQUEST_SPM:
+               {
+                       
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_REQUEST_SGXREV:
+               {
+                       PVRSRV_SGX_MISCINFO_FEATURES            *psSGXFeatures;
+                       eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+                       if(eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+                                               eError));
+                               return eError;
+                       }
+                       psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+                       
+                       psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+
+                       
+                       PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%x, sw ID 0x%x, sw Rev 0x%x\n",
+                                       psSGXFeatures->ui32CoreRev,
+                                       psSGXFeatures->ui32CoreIdSW,
+                                       psSGXFeatures->ui32CoreRevSW));
+                       PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: DDK version 0x%x, DDK build 0x%x\n",
+                                       psSGXFeatures->ui32DDKVersion,
+                                       psSGXFeatures->ui32DDKBuild));
+
+                       
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
+               {
+                       PVRSRV_SGX_MISCINFO_FEATURES            *psSGXFeatures;
+
+                       psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+                       
+                       psSGXFeatures->sDevVAEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->sDevVAddr;
+                       psSGXFeatures->pvEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+#endif
+
+                       psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+                       return PVRSRV_OK;
+               }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+               case SGX_MISC_INFO_REQUEST_MEMREAD:
+               case SGX_MISC_INFO_REQUEST_MEMCOPY:
+               {
+                       PVRSRV_ERROR eError;
+                       PVRSRV_SGX_MISCINFO_FEATURES            *psSGXFeatures;
+                       PVRSRV_SGX_MISCINFO_MEMACCESS           *psSGXMemSrc;   
+                       PVRSRV_SGX_MISCINFO_MEMACCESS           *psSGXMemDest;  
+
+                       {                               
+                               
+                               *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD;
+                               psSGXMemSrc = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessSrc;
+
+                               if(psMiscInfo->sDevVAddrSrc.uiAddr != 0)
+                               {
+                                       psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc; 
+                               }
+                               else
+                               {
+                                       return PVRSRV_ERROR_INVALID_PARAMS;
+                               }                               
+                       }
+
+                       if( psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMCOPY)
+                       {                               
+                               
+                               *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMWRITE;
+                               psSGXMemDest = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessDest;
+                               
+                               if(psMiscInfo->sDevVAddrDest.uiAddr != 0)
+                               {
+                                       psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest; 
+                               }
+                               else
+                               {
+                                       return PVRSRV_ERROR_INVALID_PARAMS;
+                               }
+                       }
+
+                       
+                       if(psMiscInfo->hDevMemContext != IMG_NULL)
+                       {
+                               SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemSrc->sPDDevPAddr);
+                               
+                               
+                               psSGXMemDest->sPDDevPAddr = psSGXMemSrc->sPDDevPAddr;
+                       }
+                       else
+                       {
+                               return PVRSRV_ERROR_INVALID_PARAMS;
+                       }
+
+                       
+                       eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+                       if(eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+                                               eError));
+                               return eError;
+                       }
+                       psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+                       if(*pui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_MEMREAD_FAIL)
+                       {
+                               return PVRSRV_ERROR_INVALID_MISCINFO;
+                       }
+#endif
+                       
+                       psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+                       return PVRSRV_OK;
+               }
+#endif 
+
+#if defined(SUPPORT_SGX_HWPERF)
+               case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
+               {
+                       PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS   *psSetHWPerfStatus = &psMiscInfo->uData.sSetHWPerfStatus;
+                       const IMG_UINT32        ui32ValidFlags = PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS |
+                                                                                                PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON |
+                                                                                                PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON |
+                                                                                                PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON;
+                       SGXMKIF_COMMAND         sCommandData = {0};
+
+                       
+                       if ((psSetHWPerfStatus->ui32NewHWPerfStatus & ~ui32ValidFlags) != 0)
+                       {
+                               return PVRSRV_ERROR_INVALID_PARAMS;
+                       }
+
+                       #if defined(PDUMP)
+                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+                                                                 "SGX ukernel HWPerf status %u\n",
+                                                                 psSetHWPerfStatus->ui32NewHWPerfStatus);
+                       #endif 
+
+                       
+                       #if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+                       OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfGroup[0],
+                                         &psSetHWPerfStatus->aui32PerfGroup[0],
+                                         sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup));
+                       OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfBit[0],
+                                         &psSetHWPerfStatus->aui32PerfBit[0],
+                                         sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit));
+                       #if defined(PDUMP)
+                       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                                        offsetof(SGXMKIF_HOST_CTL, aui32PerfGroup),
+                                        sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup),
+                                        PDUMP_FLAGS_CONTINUOUS,
+                                        MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+                       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                                        offsetof(SGXMKIF_HOST_CTL, aui32PerfBit),
+                                        sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit),
+                                        PDUMP_FLAGS_CONTINUOUS,
+                                        MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+                       #endif 
+                       #else
+                       psDevInfo->psSGXHostCtl->ui32PerfGroup = psSetHWPerfStatus->ui32PerfGroup;
+                       #if defined(PDUMP)
+                       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                                        offsetof(SGXMKIF_HOST_CTL, ui32PerfGroup),
+                                        sizeof(psDevInfo->psSGXHostCtl->ui32PerfGroup),
+                                        PDUMP_FLAGS_CONTINUOUS,
+                                        MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+                       #endif 
+                       #endif 
+
+                       
+                       sCommandData.ui32Data[0] = psSetHWPerfStatus->ui32NewHWPerfStatus;
+                       eError = SGXScheduleCCBCommandKM(psDeviceNode,
+                                                                                        SGXMKIF_CMD_SETHWPERFSTATUS,
+                                                                                        &sCommandData,
+                                                                                        KERNEL_ID,
+                                                                                        0);
+                       return eError;
+               }
+#endif 
+
+               case SGX_MISC_INFO_DUMP_DEBUG_INFO:
+               {
+                       PVR_LOG(("User requested SGX debug info"));
+
+                       
+                       SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_FALSE);
+
+                       return PVRSRV_OK;
+               }
+
+               case SGX_MISC_INFO_PANIC:
+               {
+                       PVR_LOG(("User requested SGX panic"));
+
+                       SGXPanic(psDeviceNode->pvDevice);
+
+                       return PVRSRV_OK;
+               }
+#if defined(PVRSRV_RESOURCE_PROFILING)
+               case SGX_MISC_INFO_RESOURCEPROF_SIMPLE:
+               case SGX_MISC_INFO_RESOURCEPROF_GLOBAL:
+               {
+                       PVR_LOG(("User requested resource profiling"));
+                       SGXGetResourceProfile(psMiscInfo, psDeviceNode);
+                       return PVRSRV_OK;
+               }
+               case SGX_MISC_INFO_RESOURCEPROF_MEM_INFO:
+               {
+                       PVR_LOG(("User requested resource mem info"));
+                       SGXGetResProfMemInfo(psMiscInfo, psDeviceNode);
+                       return PVRSRV_OK;
+               }
+#endif
+               default:
+               {
+                       
+                       return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+       }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE                                      hDevHandle,
+                                                          IMG_UINT32                                   ui32ArraySize,
+                                                          PVRSRV_SGX_HWPERF_CB_ENTRY   *psClientHWPerfEntry,
+                                                          IMG_UINT32                                   *pui32DataCount,
+                                                          IMG_UINT32                                   *pui32ClockSpeed,
+                                                          IMG_UINT32                                   *pui32HostTimeStamp)
+{
+       PVRSRV_ERROR            eError = PVRSRV_OK;
+       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       SGXMKIF_HWPERF_CB       *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+       IMG_UINT                        i;
+
+       for (i = 0;
+                psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
+                i++)
+       {
+               SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+               psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
+               psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
+               psClientHWPerfEntry[i].ui32Ordinal      = psMKPerfEntry->ui32Ordinal;
+               psClientHWPerfEntry[i].ui32Info = psMKPerfEntry->ui32Info;
+               psClientHWPerfEntry[i].ui32Clocksx16 = SGXConvertTimeStamp(psDevInfo,
+                                                                                                       psMKPerfEntry->ui32TimeWraps,
+                                                                                                       psMKPerfEntry->ui32Time);
+               OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0][0],
+                                 &psMKPerfEntry->ui32Counters[0][0],
+                                 sizeof(psMKPerfEntry->ui32Counters));
+
+               psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+       }
+
+       *pui32DataCount = i;
+       *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+       *pui32HostTimeStamp = OSClockus();
+
+       return eError;
+}
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxkick.c b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxkick.c
new file mode 100644 (file)
index 0000000..9edbcbe
--- /dev/null
@@ -0,0 +1,748 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <stddef.h> 
+#include "services_headers.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#if defined (PDUMP)
+#include "sgxapi_km.h"
+#include "pdump_km.h"
+#endif
+#include "sgx_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "perproc.h"
+#include "pvr_trace_cmd.h"
+
+IMG_EXPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick,
+                        PVRSRV_PER_PROCESS_DATA *proc)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       PVRSRV_KERNEL_MEM_INFO  *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *) psCCBKick->hCCBKernelMemInfo;
+       SGXMKIF_CMDTA_SHARED *psTACmd;
+       IMG_UINT32 i;
+       struct pvr_trcmd_sgxkick *ktrace;
+       int trcmd_type;
+
+       if (!CCB_OFFSET_IS_VALID(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+
+       psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset);
+
+       trcmd_type = psCCBKick->bFirstKickOrResume ?
+                       PVR_TRCMD_SGX_FIRSTKICK : PVR_TRCMD_SGX_KICK;
+       ktrace = pvr_trcmd_reserve(trcmd_type, proc->ui32PID, proc->name,
+                               sizeof(*ktrace));
+
+
+       if (psCCBKick->hTA3DSyncInfo)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+               psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+               psTACmd->sTA3DDependency.ui32WriteOpsPendingVal   = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+               if (psCCBKick->bTADependency)
+               {
+                       psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               }
+
+               pvr_trcmd_set_syn(&ktrace->ta3d_syn, psSyncInfo);
+       } else {
+               pvr_trcmd_clear_syn(&ktrace->ta3d_syn);
+       }
+
+       if (psCCBKick->hTASyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+               psTACmd->sTATQSyncReadOpsCompleteDevVAddr  = psSyncInfo->sReadOpsCompleteDevVAddr;
+               psTACmd->sTATQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+               psTACmd->ui32TATQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+               psTACmd->ui32TATQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+               pvr_trcmd_set_syn(&ktrace->tatq_syn, psSyncInfo);
+       } else {
+               pvr_trcmd_clear_syn(&ktrace->tatq_syn);
+       }
+
+       if (psCCBKick->h3DSyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+               psTACmd->s3DTQSyncReadOpsCompleteDevVAddr  = psSyncInfo->sReadOpsCompleteDevVAddr;
+               psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+               psTACmd->ui323DTQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+               psTACmd->ui323DTQSyncWriteOpsPendingVal  = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+               pvr_trcmd_set_syn(&ktrace->_3dtq_syn, psSyncInfo);
+       } else {
+               pvr_trcmd_clear_syn(&ktrace->_3dtq_syn);
+       }
+
+       psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
+       if (psCCBKick->ui32NumTAStatusVals != 0)
+       {
+               
+               for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+               {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+                       psTACmd->sCtlTAStatusInfo[i] = psCCBKick->asTAStatusUpdate[i].sCtlStatus;
+#else
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+                       psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+                       psTACmd->sCtlTAStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+               }
+       }
+
+       psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
+       if (psCCBKick->ui32Num3DStatusVals != 0)
+       {
+               
+               for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+               {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+                       psTACmd->sCtl3DStatusInfo[i] = psCCBKick->as3DStatusUpdate[i].sCtlStatus;
+#else
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+                       psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+                       psTACmd->sCtl3DStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+               }
+       }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+       
+       psTACmd->ui32NumTASrcSyncs = psCCBKick->ui32NumTASrcSyncs;
+       for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+               psTACmd->asTASrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTACmd->asTASrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               
+               psTACmd->asTASrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+               
+               psTACmd->asTASrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+       }
+
+       psTACmd->ui32NumTADstSyncs = psCCBKick->ui32NumTADstSyncs;
+       for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+               psTACmd->asTADstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTACmd->asTADstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               
+               psTACmd->asTADstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+               
+               psTACmd->asTADstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+       }
+
+       psTACmd->ui32Num3DSrcSyncs = psCCBKick->ui32Num3DSrcSyncs;
+       for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+               psTACmd->as3DSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTACmd->as3DSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               
+               psTACmd->as3DSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+               
+               psTACmd->as3DSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+       }
+#else 
+       
+       psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
+
+       for (i = 0; i < SGX_MAX_SRC_SYNCS; i++) {
+               if (i >= psCCBKick->ui32NumSrcSyncs) {
+                       pvr_trcmd_clear_syn(&ktrace->src_syn[i]);
+                       continue;
+               }
+
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+               psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               
+               psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+               
+               psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+               pvr_trcmd_set_syn(&ktrace->src_syn[i], psSyncInfo);
+       }
+#endif
+
+       if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+       {
+               PVRSRV_KERNEL_MEM_INFO  *psHWDstSyncListMemInfo =
+                                                               (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+               SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+               IMG_UINT32      ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
+
+               PVR_ASSERT(((PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo)->ui32AllocSize >= (sizeof(SGXMKIF_HWDEVICE_SYNC_LIST) +
+                                                               (sizeof(PVRSRV_DEVICE_SYNC_OBJECT) * ui32NumDstSyncs)));
+
+               psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
+#if defined(PDUMP)
+               if (PDumpIsCaptureFrameKM())
+               {
+                       PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
+                       PDUMPMEM(IMG_NULL,
+                                        psHWDstSyncListMemInfo,
+                                        0,
+                                        sizeof(SGXMKIF_HWDEVICE_SYNC_LIST),
+                                        0,
+                                        MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+               }
+#endif
+
+               for (i=0; i<ui32NumDstSyncs; i++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+                       if (psSyncInfo)
+                       {
+                               psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+                               psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+                               psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+                               psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+                               pvr_trcmd_set_syn(&ktrace->dst_syn, psSyncInfo);
+
+       #if defined(PDUMP)
+                               if (PDumpIsCaptureFrameKM())
+                               {
+                                       IMG_UINT32 ui32ModifiedValue;
+                                       IMG_UINT32 ui32SyncOffset = offsetof(SGXMKIF_HWDEVICE_SYNC_LIST, asSyncData)
+                                                                                               + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT));
+                                       IMG_UINT32 ui32WOpsOffset = ui32SyncOffset
+                                                                                               + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal);
+                                       IMG_UINT32 ui32ROpsOffset = ui32SyncOffset
+                                                                                               + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal);
+
+                                       PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i);
+
+                                       PDUMPMEM(IMG_NULL,
+                                                        psHWDstSyncListMemInfo,
+                                                        ui32SyncOffset,
+                                                        sizeof(PVRSRV_DEVICE_SYNC_OBJECT),
+                                                        0,
+                                                        MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+                                       if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+                                               (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+                                       {
+                                               
+                                               PDUMPCOMMENT("Init RT ROpsComplete\r\n");
+                                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                                       psSyncInfo->psSyncDataMemInfoKM,
+                                                       offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+                                                       sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+                                                       0,
+                                                       MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                                               
+                                               PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+                                                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                                               psSyncInfo->psSyncDataMemInfoKM,
+                                                               offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+                                                               sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+                                                               0,
+                                                               MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                                       }
+
+                                       psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+                                       ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+                                       PDUMPCOMMENT("Modify RT %d WOpPendingVal in HWDevSyncList\r\n", i);
+
+                                       PDUMPMEM(&ui32ModifiedValue,
+                                               psHWDstSyncListMemInfo,
+                                               ui32WOpsOffset,
+                                               sizeof(IMG_UINT32),
+                                               0,
+                                               MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+                                       ui32ModifiedValue = 0;
+                                       PDUMPCOMMENT("Modify RT %d ROpsPendingVal in HWDevSyncList\r\n", i);
+
+                                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                                psHWDstSyncListMemInfo,
+                                                ui32ROpsOffset,
+                                                sizeof(IMG_UINT32),
+                                                0,
+                                               MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+                               }
+       #endif  
+                       }
+                       else
+                       {
+                               psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0;
+                               psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0;
+
+                               psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0;
+                               psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0;
+
+                               pvr_trcmd_clear_syn(&ktrace->dst_syn);
+                       }
+               }
+       } else {
+               pvr_trcmd_clear_syn(&ktrace->dst_syn);
+       }
+
+       psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY;
+
+#if defined(PDUMP)
+       if (PDumpIsCaptureFrameKM())
+       {
+               PDUMPCOMMENT("Shared part of TA command\r\n");
+
+               PDUMPMEM(psTACmd,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff,
+                                sizeof(SGXMKIF_CMDTA_SHARED),
+                                0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+               for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+               {
+                       IMG_UINT32      ui32ModifiedValue;
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+                       if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+                               (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+                       {
+                               
+                               PDUMPCOMMENT("Init RT TA-SRC ROpsComplete\r\n", i);
+                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                       psSyncInfo->psSyncDataMemInfoKM,
+                                       offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+                                       sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+                                       0,
+                                       MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                               
+                               PDUMPCOMMENT("Init RT TA-SRC WOpsComplete\r\n");
+                                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                               psSyncInfo->psSyncDataMemInfoKM,
+                                               offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+                                               sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+                                               0,
+                                               MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                       }
+
+                       psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+                       ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+                       PDUMPCOMMENT("Modify TA SrcSync %d ROpsPendingVal\r\n", i);
+
+                       PDUMPMEM(&ui32ModifiedValue,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+                                       (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+                                sizeof(IMG_UINT32),
+                                0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT("Modify TA SrcSync %d WOpPendingVal\r\n", i);
+
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                               psCCBMemInfo,
+                               psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+                                       (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+                               sizeof(IMG_UINT32),
+                               0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+               }
+
+               for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+               {
+                       IMG_UINT32      ui32ModifiedValue;
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+                       if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+                               (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+                       {
+                               
+                               PDUMPCOMMENT("Init RT TA-DST ROpsComplete\r\n", i);
+                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                       psSyncInfo->psSyncDataMemInfoKM,
+                                       offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+                                       sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+                                       0,
+                                       MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                               
+                               PDUMPCOMMENT("Init RT TA-DST WOpsComplete\r\n");
+                                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                               psSyncInfo->psSyncDataMemInfoKM,
+                                               offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+                                               sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+                                               0,
+                                               MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                       }
+
+                       psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+                       ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+                       PDUMPCOMMENT("Modify TA DstSync %d WOpPendingVal\r\n", i);
+
+                       PDUMPMEM(&ui32ModifiedValue,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+                                       (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+                                sizeof(IMG_UINT32),
+                                0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT("Modify TA DstSync %d ROpsPendingVal\r\n", i);
+
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                               psCCBMemInfo,
+                               psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+                                       (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+                               sizeof(IMG_UINT32),
+                               0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+               }
+
+               for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+               {
+                       IMG_UINT32      ui32ModifiedValue;
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+                       if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+                               (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+                       {
+                               
+                               PDUMPCOMMENT("Init RT 3D-SRC ROpsComplete\r\n", i);
+                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                       psSyncInfo->psSyncDataMemInfoKM,
+                                       offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+                                       sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+                                       0,
+                                       MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                               
+                               PDUMPCOMMENT("Init RT 3D-SRC WOpsComplete\r\n");
+                                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                               psSyncInfo->psSyncDataMemInfoKM,
+                                               offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+                                               sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+                                               0,
+                                               MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                       }
+
+                       psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+                       ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+                       PDUMPCOMMENT("Modify 3D SrcSync %d ROpsPendingVal\r\n", i);
+
+                       PDUMPMEM(&ui32ModifiedValue,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+                                       (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+                                sizeof(IMG_UINT32),
+                                0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT("Modify 3D SrcSync %d WOpPendingVal\r\n", i);
+
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                               psCCBMemInfo,
+                               psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+                                       (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+                               sizeof(IMG_UINT32),
+                               0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+               }
+#else
+               for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+               {
+                       IMG_UINT32      ui32ModifiedValue;
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+                       if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+                               (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+                       {
+                               
+                               PDUMPCOMMENT("Init RT ROpsComplete\r\n");
+                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                       psSyncInfo->psSyncDataMemInfoKM,
+                                       offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+                                       sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+                                       0,
+                                       MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                               
+                               PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+                                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                               psSyncInfo->psSyncDataMemInfoKM,
+                                               offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+                                               sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+                                               0,
+                                               MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+                       }
+
+                       psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+                       ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+                       PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
+
+                       PDUMPMEM(&ui32ModifiedValue,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+                                       (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+                                sizeof(IMG_UINT32),
+                                0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
+
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                               psCCBMemInfo,
+                               psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+                                       (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+                               sizeof(IMG_UINT32),
+                               0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+               }
+#endif
+
+               for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+               {
+#if !defined(SUPPORT_SGX_NEW_STATUS_VALS)
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+                       PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue),
+                                sizeof(IMG_UINT32),
+                                0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+               }
+
+               for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+               {
+#if !defined(SUPPORT_SGX_NEW_STATUS_VALS)
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+                       PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue),
+                                sizeof(IMG_UINT32),
+                                0,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+               }
+       }
+#endif 
+
+       pvr_trcmd_set_data(&ktrace->ctx, psCCBKick->sCommand.ui32Data[1]);
+       pvr_trcmd_commit(ktrace);
+
+       eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TA, &psCCBKick->sCommand, KERNEL_ID, 0);
+       if (eError == PVRSRV_ERROR_RETRY)
+       {
+               if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+               {
+                       for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++)
+                       {
+                               
+                               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+                               if (psSyncInfo)
+                               {
+                                       psSyncInfo->psSyncData->ui32WriteOpsPending--;
+#if defined(PDUMP)
+                                       if (PDumpIsCaptureFrameKM())
+                                       {
+                                               psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+                                       }
+#endif
+                               }
+                       }
+               }
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+               for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32ReadOpsPending--;
+               }
+               for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32WriteOpsPending--;
+               }
+               for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32ReadOpsPending--;
+               }
+#else
+               for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32ReadOpsPending--;
+               }
+#endif
+
+               return eError;
+       }
+       else if (PVRSRV_OK != eError)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: SGXScheduleCCBCommandKM failed."));
+               return eError;
+       }
+
+
+#if defined(NO_HARDWARE)
+
+
+       
+       if (psCCBKick->hTA3DSyncInfo)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+               if (psCCBKick->bTADependency)
+               {
+                       psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+               }
+       }
+
+       if (psCCBKick->hTASyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+               psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+       }
+
+       if (psCCBKick->h3DSyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+               psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+       }
+
+       
+       for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+       {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+               PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo;
+               
+               *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+                                               + (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr
+                                               - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#else
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+               psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#endif
+       }
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+       
+       for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+               psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+       }
+       for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+               psSyncInfo->psSyncData->ui32WriteOpsComplete =  psSyncInfo->psSyncData->ui32WriteOpsPending;
+       }
+       for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+               psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+       }
+#else
+       
+       for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+               psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+       }
+#endif
+
+       if (psCCBKick->bTerminateOrAbort)
+       {
+               if (psCCBKick->ui32NumDstSyncObjects > 0)
+               {
+                       PVRSRV_KERNEL_MEM_INFO  *psHWDstSyncListMemInfo =
+                                                               (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+                       SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+
+                       for (i=0; i<psCCBKick->ui32NumDstSyncObjects; i++)
+                       {
+                               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+                               if (psSyncInfo)
+                                       psSyncInfo->psSyncData->ui32WriteOpsComplete = psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal+1;
+                       }
+               }
+
+               
+               for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+               {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+                       PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo;
+                       
+                       *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+                                                       + (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr
+                                                       - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#else
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#endif
+               }
+       }
+#endif
+
+       return eError;
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxpower.c b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxpower.c
new file mode 100644 (file)
index 0000000..bac5d1b
--- /dev/null
@@ -0,0 +1,474 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE             *psDeviceNode,
+                                                               SGX_TIMING_INFORMATION  *psSGXTimingInfo,
+                                                               IMG_HANDLE                              *phTimer)
+{
+       
+
+
+       *phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
+                                                 1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
+       if(*phTimer == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       return PVRSRV_OK;
+}
+#endif 
+
+
+static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE     *psDeviceNode)
+{
+       PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+       SGX_TIMING_INFORMATION  sSGXTimingInfo = {0};
+#else
+       SGX_DEVICE_MAP          *psSGXDeviceMap;
+#endif
+       IMG_UINT32              ui32ActivePowManSampleRate;
+       SGX_TIMING_INFORMATION  *psSGXTimingInfo;
+
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+       psSGXTimingInfo = &sSGXTimingInfo;
+       SysGetSGXTimingInformation(psSGXTimingInfo);
+#else
+       SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+                                                 (IMG_VOID**)&psSGXDeviceMap);
+       psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+       {
+               PVRSRV_ERROR                    eError;
+               IMG_UINT32      ui32OlduKernelFreq;
+
+               if (psDevInfo->hTimer != IMG_NULL)
+               {
+                       ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
+                       if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
+                       {
+                               
+
+                               IMG_HANDLE hNewTimer;
+                               
+                               eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
+                               if (eError == PVRSRV_OK)
+                               {
+                                       eError = OSRemoveTimer(psDevInfo->hTimer);
+                                       if (eError != PVRSRV_OK)
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer"));
+                                       }
+                                       psDevInfo->hTimer = hNewTimer;
+                               }
+                               else
+                               {
+                                       
+                               }
+                       }
+               }
+               else
+               {
+                       eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer);
+                       if (eError != PVRSRV_OK)
+                       {
+                               return eError;
+                       }
+               }
+
+               psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
+                       psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
+       }
+#endif 
+
+       
+       psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
+       psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
+
+       
+       psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
+#if defined(PDUMP)
+       PDUMPCOMMENT("Host Control - Microkernel clock");
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                        offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
+                        sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                        MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif 
+
+       if (psSGXTimingInfo->bEnableActivePM)
+       {
+               ui32ActivePowManSampleRate =
+                       psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+               
+
+
+
+
+
+
+               ui32ActivePowManSampleRate += 1;
+       }
+       else
+       {
+               ui32ActivePowManSampleRate = 0;
+       }
+
+       psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate;
+#if defined(PDUMP)
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                        offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
+                        sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                        MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif 
+
+       return PVRSRV_OK;
+}
+
+
+static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO       *psDevInfo)
+{
+       #if defined(SUPPORT_HW_RECOVERY)
+       PVRSRV_ERROR    eError;
+
+       eError = OSEnableTimer(psDevInfo->hTimer);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer"));
+       }
+       #else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       #endif 
+}
+
+
+static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO      *psDevInfo,
+                                                                          IMG_UINT32                   ui32Register,
+                                                                          IMG_UINT32                   ui32RegisterValue,
+                                                                          IMG_CHAR                             *pszComment)
+{
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32Register);
+       PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
+       PVR_UNREFERENCED_PARAMETER(pszComment);
+
+       #if !defined(NO_HARDWARE)
+       PVR_ASSERT(psDevInfo != IMG_NULL);
+
+        
+       if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
+                                               0,
+                                               ui32RegisterValue,
+                                               MAX_HW_TIME_US,
+                                               MAX_HW_TIME_US/WAIT_TRY_COUNT,
+                                               IMG_FALSE) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment));
+               PVR_DBG_BREAK;
+       }
+       #endif 
+
+       PDUMPCOMMENT("%s", pszComment);
+       PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue);
+}
+
+
+PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE                              hDevHandle,
+                                                          PVRSRV_DEV_POWER_STATE       eNewPowerState,
+                                                          PVRSRV_DEV_POWER_STATE       eCurrentPowerState)
+{
+       if ((eNewPowerState != eCurrentPowerState) &&
+               (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
+       {
+               PVRSRV_ERROR            eError;
+               PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
+               PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+               IMG_UINT32                      ui32PowerCmd, ui32CompleteStatus;
+               SGXMKIF_COMMAND         sCommand = {0};
+               IMG_UINT32                      ui32Core;
+
+               #if defined(SUPPORT_HW_RECOVERY)
+               
+               eError = OSDisableTimer(psDevInfo->hTimer);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
+                       return eError;
+               }
+               #endif 
+
+               if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+               {
+                       
+                       ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
+                       ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
+                       PDUMPCOMMENT("SGX power off request");
+               }
+               else
+               {
+                       
+                       ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
+                       ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
+                       PDUMPCOMMENT("SGX idle request");
+               }
+
+               sCommand.ui32Data[1] = ui32PowerCmd;
+
+               eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command"));
+                       return eError;
+               }
+
+               
+               #if !defined(NO_HARDWARE)
+               if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
+                                                       ui32CompleteStatus,
+                                                       ui32CompleteStatus,
+                                                       MAX_HW_TIME_US,
+                                                       MAX_HW_TIME_US/WAIT_TRY_COUNT,
+                                                       IMG_FALSE) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+                       PVR_DBG_BREAK;
+               }
+               #endif 
+
+               #if defined(PDUMP)
+               PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
+               PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+                                       offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+                                       ui32CompleteStatus,
+                                       ui32CompleteStatus,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       0,
+                                       MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+               #endif 
+
+               for (ui32Core = 0; ui32Core < SGX_FEATURE_MP_CORE_COUNT; ui32Core++)
+               {
+                       
+                       SGXPollForClockGating(psDevInfo,
+                                                                 SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
+                                                                 psDevInfo->ui32ClkGateStatusMask,
+                                                                 "Wait for SGX clock gating");
+               }
+
+               #if defined(SGX_FEATURE_MP)
+               
+               SGXPollForClockGating(psDevInfo,
+                                                         psDevInfo->ui32MasterClkGateStatusReg,
+                                                         psDevInfo->ui32MasterClkGateStatusMask,
+                                                         "Wait for SGX master clock gating");
+
+               SGXPollForClockGating(psDevInfo,
+                                                         psDevInfo->ui32MasterClkGateStatus2Reg,
+                                                         psDevInfo->ui32MasterClkGateStatus2Mask,
+                                                         "Wait for SGX master clock gating (2)");
+               #endif 
+
+               if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+               {
+                       
+                       eError = SGXDeinitialise(psDevInfo);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %u", eError));
+                               return eError;
+                       }
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE                             hDevHandle,
+                                                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                                                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState)
+{
+       if ((eNewPowerState != eCurrentPowerState) &&
+               (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
+       {
+               PVRSRV_ERROR            eError;
+               PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
+               PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+               SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+               
+               psSGXHostCtl->ui32PowerStatus = 0;
+               #if defined(PDUMP)
+               PDUMPCOMMENT("Host Control - Reset power status");
+               PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                                offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+                                sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                                MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+               #endif 
+
+               if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+               {
+                       
+
+                       
+
+                       eError = SGXUpdateTimingInfo(psDeviceNode);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+                               return eError;
+                       }
+
+                       
+
+                       eError = SGXInitialise(psDevInfo, IMG_FALSE);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed"));
+                               return eError;
+                       }
+               }
+               else
+               {
+                       
+
+                       SGXMKIF_COMMAND         sCommand = {0};
+
+                       sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
+                       eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %u", eError));
+                               return eError;
+                       }
+               }
+
+               SGXStartTimer(psDevInfo);
+       }
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE                                hDevHandle,
+                                                                        IMG_BOOL                               bIdleDevice,
+                                                                        PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+       if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+       {
+               if (bIdleDevice)
+               {
+                       
+                       PDUMPSUSPEND();
+
+                       eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
+                                                                         PVRSRV_DEV_POWER_STATE_ON);
+
+                       if (eError != PVRSRV_OK)
+                       {
+                               PDUMPRESUME();
+                               return eError;
+                       }
+               }
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %uHz",
+                       psDevInfo->ui32CoreClockSpeed));
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE                               hDevHandle,
+                                                                         IMG_BOOL                                      bIdleDevice,
+                                                                         PVRSRV_DEV_POWER_STATE        eCurrentPowerState)
+{
+       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       IMG_UINT32                      ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
+
+       PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
+
+       if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+       {
+               PVRSRV_ERROR eError;
+
+               
+
+               eError = SGXUpdateTimingInfo(psDeviceNode);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+                       return eError;
+               }
+
+               if (bIdleDevice)
+               {
+                       
+                       eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
+                                                                          PVRSRV_DEV_POWER_STATE_IDLE);
+
+                       PDUMPRESUME();
+
+                       if (eError != PVRSRV_OK)
+                       {
+                               return eError;
+                       }
+               }
+               else
+               {
+                       SGXStartTimer(psDevInfo);
+               }
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %uHz to %uHz",
+                       ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
+
+       return PVRSRV_OK;
+}
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxreset.c b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxreset.c
new file mode 100644 (file)
index 0000000..847ca24
--- /dev/null
@@ -0,0 +1,510 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+
+#include "pdump_km.h"
+
+
+static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO   *psDevInfo,
+                                                                 IMG_BOOL                              bResetBIF,
+                                                                 IMG_UINT32                    ui32PDUMPFlags,
+                                                                 IMG_BOOL                              bPDump)
+{
+       IMG_UINT32 ui32SoftResetRegVal;
+
+#if defined(SGX_FEATURE_MP)
+       ui32SoftResetRegVal =
+                                       EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK  |
+                                       EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK  |
+                                       EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK;
+
+#if defined(SGX_FEATURE_PTLA)
+       ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_MASK;
+#endif
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+       ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK;
+#endif
+
+       if (bResetBIF)
+       {
+               ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK;
+       }
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal);
+       if (bPDump)
+       {
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+       }
+#endif 
+
+       ui32SoftResetRegVal =
+                                       
+                                       EUR_CR_SOFT_RESET_DPM_RESET_MASK |
+                                       EUR_CR_SOFT_RESET_TA_RESET_MASK  |
+                                       EUR_CR_SOFT_RESET_USE_RESET_MASK |
+                                       EUR_CR_SOFT_RESET_ISP_RESET_MASK |
+                                       EUR_CR_SOFT_RESET_TSP_RESET_MASK;
+
+#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TE_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MTE_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MTE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ISP2_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ISP2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PDS_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PDS_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PBE_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PBE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MADD_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MADD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ITR_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ITR_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TEX_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TEX_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_VDM_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_VDM_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK)
+       ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK;
+#endif
+
+#if !defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif 
+
+       if (bResetBIF)
+       {
+               ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK;
+       }
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32SoftResetRegVal);
+       if (bPDump)
+       {
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+       }
+}
+
+
+static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO       *psDevInfo,
+                                                         IMG_UINT32                    ui32PDUMPFlags,
+                                                         IMG_BOOL                              bPDump)
+{
+#if !defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif 
+
+       
+       OSWaitus(100 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+       if (bPDump)
+       {
+               PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
+#if defined(PDUMP)
+               PDumpRegRead(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32PDUMPFlags);
+#endif
+       }
+
+}
+
+
+static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO     *psDevInfo,
+                                                           IMG_UINT32                  ui32PDUMPFlags,
+                                                               IMG_BOOL                        bPDump)
+{
+       IMG_UINT32 ui32RegVal;
+
+       
+#if defined(EUR_CR_BIF_CTRL_INVAL)
+       ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal);
+       if (bPDump)
+       {
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL_INVAL, ui32RegVal, ui32PDUMPFlags);
+       }
+#else
+       ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+       if (bPDump)
+       {
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+       }
+
+       ui32RegVal = 0;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+       if (bPDump)
+       {
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+       }
+#endif
+       SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       {
+               
+
+
+               if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
+                                                       0,
+                                                       EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
+                                                       MAX_HW_TIME_US,
+                                                       MAX_HW_TIME_US/WAIT_TRY_COUNT,
+                                                       IMG_FALSE) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"Wait for DC invalidate failed."));
+                       PVR_DBG_BREAK;
+               }
+
+               if (bPDump)
+               {
+                       PDUMPREGPOLWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags);
+               }
+       }
+#endif 
+}
+
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO   *psDevInfo,
+                                 IMG_BOOL                              bHardwareRecovery,
+                                 IMG_UINT32                    ui32PDUMPFlags)
+{
+       IMG_UINT32 ui32RegVal;
+#if defined(EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK)
+       const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK;
+#else
+       const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
+#endif
+
+#ifndef PDUMP
+       PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif 
+
+       psDevInfo->ui32NumResets++;
+
+       PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n");
+
+#if defined(FIX_HW_BRN_23944)
+       
+       ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+       SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+       ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+       if (ui32RegVal & ui32BifFaultMask)
+       {
+               
+               ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK;
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+               SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+               ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+               SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+       }
+#endif 
+
+       
+       SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
+
+       SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+       
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+       
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags);
+#endif
+
+       ui32RegVal = 0;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+#if defined(SGX_FEATURE_MP)
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_CTRL, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+#endif 
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK_SET, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+#endif 
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       {
+               IMG_UINT32      ui32DirList, ui32DirListReg;
+
+               for (ui32DirList = 1;
+                        ui32DirList < SGX_FEATURE_BIF_NUM_DIRLISTS;
+                        ui32DirList++)
+               {
+                       ui32DirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (ui32DirList - 1);
+                       OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32DirListReg, ui32RegVal);
+                       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, ui32DirListReg, ui32RegVal, ui32PDUMPFlags);
+               }
+       }
+#endif 
+
+#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
+       
+
+       ui32RegVal      = (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) |
+                                 (7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) |
+                                 (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT);
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags);
+#endif 
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+#if defined(SGX_FEATURE_MP)
+       #if defined(SGX_BYPASS_SYSTEM_CACHE)
+               #error SGX_BYPASS_SYSTEM_CACHE not supported
+       #else
+               ui32RegVal = EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_MASK |
+               #if defined(FIX_HW_BRN_30954)
+                                               EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_MASK |
+               #endif
+                                               (0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT);
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+               PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+
+               ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_MASK;
+       #if defined(FIX_HW_BRN_31195)
+               ui32RegVal |= EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE0_MASK |
+                               EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE1_MASK |
+                               EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE2_MASK |
+                               EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_MASK |
+                               EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_MASK;
+       #endif
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+               PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+       #endif 
+#else
+       #if defined(SGX_BYPASS_SYSTEM_CACHE)
+               
+               ui32RegVal = MNE_CR_CTRL_BYPASS_ALL_MASK;
+       #else
+               #if defined(FIX_HW_BRN_26620)
+                       ui32RegVal = 0;
+               #else
+                       
+                       ui32RegVal = MNE_CR_CTRL_BYP_CC_MASK;
+               #endif
+       #endif 
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, MNE_CR_CTRL, ui32RegVal);
+       PDUMPREG(SGX_PDUMPREG_NAME, MNE_CR_CTRL, ui32RegVal);
+#endif 
+#endif 
+
+       if (bHardwareRecovery)
+       {
+               
+
+
+
+
+
+
+               ui32RegVal = (IMG_UINT32)psDevInfo->sBIFResetPDDevPAddr.uiAddr;
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+
+               SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+               
+               SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+               SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+               SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+               
+
+               for (;;)
+               {
+                       IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+                       IMG_DEV_VIRTADDR sBifFault;
+                       IMG_UINT32 ui32PDIndex, ui32PTIndex;
+
+                       if ((ui32BifIntStat & ui32BifFaultMask) == 0)
+                       {
+                               break;
+                       }
+
+                       
+
+
+                       sBifFault.uiAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+                       PVR_DPF((PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x", ui32BifIntStat, sBifFault.uiAddr));
+                       ui32PDIndex = sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+                       ui32PTIndex = (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+                       
+                       SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE);
+
+                       
+                       psDevInfo->pui32BIFResetPD[ui32PDIndex] = (psDevInfo->sBIFResetPTDevPAddr.uiAddr
+                                                                                                       >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+                                                                                                       | SGX_MMU_PDE_PAGE_SIZE_4K
+                                                                                                       | SGX_MMU_PDE_VALID;
+                       psDevInfo->pui32BIFResetPT[ui32PTIndex] = (psDevInfo->sBIFResetPageDevPAddr.uiAddr
+                                                                                                       >>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+                                                                                                       | SGX_MMU_PTE_VALID;
+
+                       
+                       ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+                       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32RegVal);
+                       ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+                       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32RegVal);
+
+                       SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+                       
+                       SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE);
+                       SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+                       
+                       SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+                       
+                       psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
+                       psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
+               }
+       }
+       else
+       {
+               
+               SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+               SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+       }       
+
+       
+
+       #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       
+       ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
+
+       #if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
+       
+       ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
+       #endif 
+
+       #if defined(FIX_HW_BRN_23410)
+       
+       ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
+       #endif 
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+       #endif 
+
+       {
+               IMG_UINT32      ui32EDMDirListReg;
+
+               
+               #if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
+               ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
+               #else
+               
+               ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
+               #endif 
+
+#if defined(FIX_HW_BRN_28011)
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+               PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+#endif
+
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+               PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+       }
+
+#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
+       
+       #if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0)
+               #error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment"
+       #endif
+       
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags);
+#endif
+
+       
+       SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+       PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX"));
+
+       
+       ui32RegVal = 0;
+#if defined(SGX_FEATURE_MP)
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+#endif 
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
+       PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+       
+       SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+       PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
+}
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxtransfer.c b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
new file mode 100644 (file)
index 0000000..f804650
--- /dev/null
@@ -0,0 +1,615 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if defined(TRANSFER_QUEUE)
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxinfo.h"
+#include "sysconfig.h"
+#include "regpaths.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfokm.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "perproc.h"
+#include "pvr_trace_cmd.h"
+
+IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick,
+                                            PVRSRV_PER_PROCESS_DATA *proc)
+{
+       PVRSRV_KERNEL_MEM_INFO  *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+       SGXMKIF_COMMAND sCommand = {0};
+       SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
+       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 loop;
+       struct pvr_trcmd_sgxtransfer *ttrace;
+
+#if defined(PDUMP)
+       IMG_BOOL bPersistentProcess = IMG_FALSE;
+       
+       {
+               PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+               if(psPerProc != IMG_NULL)
+               {
+                       bPersistentProcess = psPerProc->bPDumpPersistent;
+               }
+       }
+#endif 
+
+       if (!CCB_OFFSET_IS_VALID(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: Invalid CCB offset"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       
+       
+       psSharedTransferCmd =  CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+       ttrace = pvr_trcmd_reserve(PVR_TRCMD_SGX_TFER_KICK, proc->ui32PID,
+                                  proc->name, sizeof(*ttrace));
+
+       if (psKick->hTASyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+               psSharedTransferCmd->ui32TASyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               psSharedTransferCmd->ui32TASyncReadOpsPendingVal  = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               pvr_trcmd_set_syn(&ttrace->ta_syn, psSyncInfo);
+       }
+       else
+       {
+               psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+               psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+
+               pvr_trcmd_clear_syn(&ttrace->ta_syn);
+       }
+
+       if (psKick->h3DSyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+               psSharedTransferCmd->ui323DSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               psSharedTransferCmd->ui323DSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               pvr_trcmd_set_syn(&ttrace->_3d_syn, psSyncInfo);
+       }
+       else
+       {
+               psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+               psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+
+               pvr_trcmd_clear_syn(&ttrace->_3d_syn);
+       }
+
+       psSharedTransferCmd->ui32NumSrcSyncs = psKick->ui32NumSrcSync;
+       psSharedTransferCmd->ui32NumDstSyncs = psKick->ui32NumDstSync;
+       if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+       {
+               for (loop=0; loop<psKick->ui32NumSrcSync; loop++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+
+                       psSharedTransferCmd->asSrcSyncs[loop].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+                       psSharedTransferCmd->asSrcSyncs[loop].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+                       psSharedTransferCmd->asSrcSyncs[loop].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+                       psSharedTransferCmd->asSrcSyncs[loop].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               }
+               for (loop=0; loop<psKick->ui32NumDstSync; loop++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+
+                       psSharedTransferCmd->asDstSyncs[loop].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+                       psSharedTransferCmd->asDstSyncs[loop].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+                       psSharedTransferCmd->asDstSyncs[loop].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+                       psSharedTransferCmd->asDstSyncs[loop].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               }
+
+               
+               for (loop = 0; loop < SGX_MAX_TRANSFER_SYNC_OPS; loop++)
+               {
+                       if (loop >= psKick->ui32NumSrcSync) {
+                               pvr_trcmd_clear_syn(&ttrace->src_syn[loop]);
+                               continue;
+                       }
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+                       psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+                       pvr_trcmd_set_syn(&ttrace->src_syn[loop], psSyncInfo);
+               }
+               for (loop = 0; loop < SGX_MAX_TRANSFER_SYNC_OPS; loop++)
+               {
+                       if (loop >= psKick->ui32NumDstSync) {
+                               pvr_trcmd_clear_syn(&ttrace->dst_syn[loop]);
+                               continue;
+                       }
+
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+                       psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+                       pvr_trcmd_set_syn(&ttrace->dst_syn[loop], psSyncInfo);
+               }
+       }
+
+#if defined(PDUMP)
+       if ((PDumpIsCaptureFrameKM()
+       || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) 
+       &&  (bPersistentProcess == IMG_FALSE) )
+       {
+               PDUMPCOMMENT("Shared part of transfer command\r\n");
+               PDUMPMEM(psSharedTransferCmd,
+                               psCCBMemInfo,
+                               psKick->ui32CCBDumpWOff,
+                               sizeof(SGXMKIF_TRANSFERCMD_SHARED),
+                               psKick->ui32PDumpFlags,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+
+               if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+               {
+                       for (loop=0; loop<psKick->ui32NumSrcSync ; loop++)
+                       {
+                               psSyncInfo = psKick->ahSrcSyncInfo[loop];
+       
+                               PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n");
+                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                               psCCBMemInfo,
+                                               psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+                                               sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+                                               psKick->ui32PDumpFlags,
+                                               MAKEUNIQUETAG(psCCBMemInfo));
+
+                               PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n");
+                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                               psCCBMemInfo,
+                                               psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+                                               sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+                                               psKick->ui32PDumpFlags,
+                                               MAKEUNIQUETAG(psCCBMemInfo));
+
+                       }
+               }
+               if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+               {
+                       for (loop=0; loop< psKick->ui32NumDstSync; loop++)
+                       {
+                               psSyncInfo = psKick->ahDstSyncInfo[loop];
+       
+                               PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n");
+                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                               psCCBMemInfo,
+                                               psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)  ,
+                                               sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+                                               psKick->ui32PDumpFlags,
+                                               MAKEUNIQUETAG(psCCBMemInfo));
+
+                               PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n");
+                               PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                               psCCBMemInfo,
+                                               psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+                                               sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+                                               psKick->ui32PDumpFlags,
+                                               MAKEUNIQUETAG(psCCBMemInfo));
+
+                       }
+               }
+
+               
+               if((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING)== 0UL)
+               {
+                       for (loop=0; loop<(psKick->ui32NumSrcSync); loop++)
+                       {
+                               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+                               psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+                       }
+               }
+
+               if((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+               {
+                       for (loop=0; loop<(psKick->ui32NumDstSync); loop++)
+                       {
+                               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+                               psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+                       }
+               }
+       }               
+#endif
+
+       sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+
+       pvr_trcmd_set_data(&ttrace->ctx,
+                       psKick->sHWTransferContextDevVAddr.uiAddr);
+       pvr_trcmd_commit(ttrace);
+
+       
+       eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TRANSFER, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags);
+
+       if (eError == PVRSRV_ERROR_RETRY)
+       {
+               
+               if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+               {
+                       if (psKick->ui32NumSrcSync > 0)
+                       {
+                               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+                               psSyncInfo->psSyncData->ui32ReadOpsPending--;
+                       }
+                       if (psKick->ui32NumDstSync > 0)
+                       {
+                               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+                               psSyncInfo->psSyncData->ui32WriteOpsPending--;
+                       }
+#if defined(PDUMP)
+                       if (PDumpIsCaptureFrameKM()
+                       || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+                       {
+                               if (psKick->ui32NumSrcSync > 0)
+                               {
+                                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+                                       psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+                               }
+                               if (psKick->ui32NumDstSync > 0)
+                               {
+                                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+                                       psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+                               }
+                       }
+#endif
+               }
+
+               
+               if (psKick->hTASyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+                       psSyncInfo->psSyncData->ui32WriteOpsPending--;
+               }
+
+               
+               if (psKick->h3DSyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+                       psSyncInfo->psSyncData->ui32WriteOpsPending--;
+               }
+       }
+
+       else if (PVRSRV_OK != eError)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: SGXScheduleCCBCommandKM failed."));
+               return eError;
+       }
+       
+
+#if defined(NO_HARDWARE)
+       if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0)
+       {
+               IMG_UINT32 i;
+
+               
+               for(i = 0; i < psKick->ui32NumSrcSync; i++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+               }
+
+               for(i = 0; i < psKick->ui32NumDstSync; i++)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+               }
+
+               if (psKick->hTASyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+                       psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+               }
+
+               if (psKick->h3DSyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+                       psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+               }
+       }
+#endif
+
+       return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick)
+                                           
+{
+       PVRSRV_KERNEL_MEM_INFO  *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+       SGXMKIF_COMMAND sCommand = {0};
+       SGXMKIF_2DCMD_SHARED *ps2DCmd;
+       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 i;
+#if defined(PDUMP)
+       IMG_BOOL bPersistentProcess = IMG_FALSE;
+       
+       {
+               PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+               if(psPerProc != IMG_NULL)
+               {
+                       bPersistentProcess = psPerProc->bPDumpPersistent;
+               }
+       }
+#endif 
+
+       if (!CCB_OFFSET_IS_VALID(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       
+       
+       ps2DCmd =  CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+       OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd));
+
+       
+       if (psKick->hTASyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+               ps2DCmd->sTASyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               ps2DCmd->sTASyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr  = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr   = psSyncInfo->sReadOpsCompleteDevVAddr;
+       }
+
+       
+       if (psKick->h3DSyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+               ps2DCmd->s3DSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               ps2DCmd->s3DSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+       }
+
+       
+       ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
+       for (i = 0; i < psKick->ui32NumSrcSync; i++)
+       {
+               psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+               ps2DCmd->sSrcSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+               ps2DCmd->sSrcSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               ps2DCmd->sSrcSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               ps2DCmd->sSrcSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+       }
+
+       if (psKick->hDstSyncInfo != IMG_NULL)
+       {
+               psSyncInfo = psKick->hDstSyncInfo;
+
+               ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+               ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+               ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+       }
+
+       
+       for (i = 0; i < psKick->ui32NumSrcSync; i++)
+       {
+               psSyncInfo = psKick->ahSrcSyncInfo[i];
+               psSyncInfo->psSyncData->ui32ReadOpsPending++;
+       }
+
+       if (psKick->hDstSyncInfo != IMG_NULL)
+       {
+               psSyncInfo = psKick->hDstSyncInfo;
+               psSyncInfo->psSyncData->ui32WriteOpsPending++;
+       }
+
+#if defined(PDUMP)
+       if ((PDumpIsCaptureFrameKM()
+       || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+       &&  (bPersistentProcess == IMG_FALSE) )
+       {
+               
+               PDUMPCOMMENT("Shared part of 2D command\r\n");
+               PDUMPMEM(ps2DCmd,
+                               psCCBMemInfo,
+                               psKick->ui32CCBDumpWOff,
+                               sizeof(SGXMKIF_2DCMD_SHARED),
+                               psKick->ui32PDumpFlags,
+                               MAKEUNIQUETAG(psCCBMemInfo));
+
+               for (i = 0; i < psKick->ui32NumSrcSync; i++)
+               {
+                       psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+                       PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                       psCCBMemInfo,
+                                       psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal),
+                                       sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+                                       psKick->ui32PDumpFlags,
+                                       MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                       psCCBMemInfo,
+                                       psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal),
+                                       sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+                                       psKick->ui32PDumpFlags,
+                                       MAKEUNIQUETAG(psCCBMemInfo));
+               }
+
+               if (psKick->hDstSyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = psKick->hDstSyncInfo;
+
+                       PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                       psCCBMemInfo,
+                                       psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal),
+                                       sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+                                       psKick->ui32PDumpFlags,
+                                       MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                       psCCBMemInfo,
+                                       psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal),
+                                       sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+                                       psKick->ui32PDumpFlags,
+                                       MAKEUNIQUETAG(psCCBMemInfo));
+               }
+
+               
+               for (i = 0; i < psKick->ui32NumSrcSync; i++)
+               {
+                       psSyncInfo = psKick->ahSrcSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+               }
+
+               if (psKick->hDstSyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = psKick->hDstSyncInfo;
+                       psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+               }
+       }               
+#endif
+
+       sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr;
+       
+       eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_2D, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags);     
+
+       if (eError == PVRSRV_ERROR_RETRY)
+       {
+               
+
+#if defined(PDUMP)
+               if (PDumpIsCaptureFrameKM())
+               {
+                       for (i = 0; i < psKick->ui32NumSrcSync; i++)
+                       {
+                               psSyncInfo = psKick->ahSrcSyncInfo[i];
+                               psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+                       }
+
+                       if (psKick->hDstSyncInfo != IMG_NULL)
+                       {
+                               psSyncInfo = psKick->hDstSyncInfo;
+                               psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+                       }
+               }
+#endif
+
+               for (i = 0; i < psKick->ui32NumSrcSync; i++)
+               {
+                       psSyncInfo = psKick->ahSrcSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32ReadOpsPending--;
+               }
+
+               if (psKick->hDstSyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = psKick->hDstSyncInfo;
+                       psSyncInfo->psSyncData->ui32WriteOpsPending--;
+               }
+
+               
+               if (psKick->hTASyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+                       psSyncInfo->psSyncData->ui32WriteOpsPending--;
+               }
+
+               
+               if (psKick->h3DSyncInfo != IMG_NULL)
+               {
+                       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+                       psSyncInfo->psSyncData->ui32WriteOpsPending--;
+               }
+       }
+
+       
+
+
+#if defined(NO_HARDWARE)
+       
+       for(i = 0; i < psKick->ui32NumSrcSync; i++)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+               psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+       }
+
+       if (psKick->hDstSyncInfo != IMG_NULL)
+       {
+       psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hDstSyncInfo;
+       psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+       }
+
+       if (psKick->hTASyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+               psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+       }
+
+       if (psKick->h3DSyncInfo != IMG_NULL)
+       {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+               psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+       }
+#endif
+
+       return eError;
+}
+#endif 
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxutils.c b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxutils.c
new file mode 100644 (file)
index 0000000..de0bf63
--- /dev/null
@@ -0,0 +1,1012 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgx_bridge_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>      
+#include <linux/string.h>      
+#else
+#include <stdio.h>
+#endif
+#include "psb_powermgmt.h"
+
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE       * psDeviceNode, IMG_UINT32 ui32CallerID);
+#endif
+
+
+
+static IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE     * psDeviceNode,
+                                                                               IMG_UINT32           ui32CallerID)
+{
+       PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       SGXMKIF_HOST_CTL        *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+       
+       psSGXHostCtl->ui32NumActivePowerEvents++;
+
+       if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0)
+       {
+               
+
+
+               if (ui32CallerID == ISR_ID)
+               {
+                       psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+               }
+               else
+               {
+                       SGXScheduleProcessQueuesKM(psDeviceNode);
+               }
+       }
+}
+
+
+IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE   *psDeviceNode,
+                                                                 IMG_UINT32                    ui32CallerID)
+{
+       PVRSRV_ERROR            eError = PVRSRV_OK;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       SGXMKIF_HOST_CTL        *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+       if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) &&
+               ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0))
+       {
+               
+               psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
+               
+               PDUMPSUSPEND();
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+               
+
+
+               eError = SysPowerDownMISR(psDeviceNode, ui32CallerID);
+#else
+               eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+                                                                                        PVRSRV_DEV_POWER_STATE_OFF,
+                                                                                        ui32CallerID, IMG_FALSE);
+               if (eError == PVRSRV_OK)
+               {
+                       SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
+               }
+#endif
+               if (eError == PVRSRV_ERROR_RETRY)
+               {
+                       
+
+                       psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+                       eError = PVRSRV_OK;
+               }
+
+               
+               PDUMPRESUME();
+       }
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError));
+       }
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGXAcquireKernelCCBSlot)
+#endif
+static INLINE SGXMKIF_COMMAND * SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *psCCB)
+{
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               if(((*psCCB->pui32WriteOffset + 1) & 255) != *psCCB->pui32ReadOffset)
+               {
+                       return &psCCB->psCommands[*psCCB->pui32WriteOffset];
+               }
+
+               OSSleepms(1);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       
+       return IMG_NULL;
+}
+
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO  *psDevInfo,
+                                                                  SGXMKIF_CMD_TYPE             eCmdType,
+                                                                  SGXMKIF_COMMAND              *psCommandData,
+                                                                  IMG_UINT32                   ui32CallerID,
+                                                                  IMG_UINT32                   ui32PDumpFlags)
+{
+       PVRSRV_SGX_CCB_INFO *psKernelCCB;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       SGXMKIF_COMMAND *psSGXCommand;
+       SYS_DATA *psSysData;
+#if defined(PDUMP)
+       IMG_VOID *pvDumpCommand;
+       IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
+       IMG_BOOL bPersistentProcess = IMG_FALSE;
+#else
+       PVR_UNREFERENCED_PARAMETER(ui32CallerID);
+       PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif
+
+#if defined(FIX_HW_BRN_28889)
+       
+
+
+
+       if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) && 
+                ((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) &&
+                ((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0))
+       {
+       #if defined(PDUMP)
+               PVRSRV_KERNEL_MEM_INFO  *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+       #endif
+               SGXMKIF_HOST_CTL        *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+               SGXMKIF_COMMAND         sCacheCommand = {0};
+
+               eError = SGXScheduleCCBCommand(psDevInfo,
+                                                                          SGXMKIF_CMD_PROCESS_QUEUES,
+                                                                          &sCacheCommand,
+                                                                          ui32CallerID,
+                                                                          ui32PDumpFlags);
+               if (eError != PVRSRV_OK)
+               {
+                       goto Exit;
+               }
+               
+               
+               #if !defined(NO_HARDWARE)
+               if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus,
+                                                 PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+                                                 PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+                                                 2 * MAX_HW_TIME_US,
+                                                 MAX_HW_TIME_US/WAIT_TRY_COUNT,
+                                                 IMG_FALSE) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommand: Wait for uKernel to Invalidate BIF cache failed"));
+                       PVR_DBG_BREAK;
+               }
+               #endif
+       
+               #if defined(PDUMP)
+               
+               PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete");
+               PDUMPMEMPOL(psSGXHostCtlMemInfo,
+                                       offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus),
+                                       PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+                                       PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       0,
+                                       MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+               #endif 
+       
+               psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE);
+               PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+       }
+#endif
+       
+#if defined(PDUMP)
+       
+       {
+               PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+               if(psPerProc != IMG_NULL)
+               {
+                       bPersistentProcess = psPerProc->bPDumpPersistent;
+               }
+       }
+#endif 
+       psKernelCCB = psDevInfo->psKernelCCBInfo;
+
+       psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
+
+       
+       if(!psSGXCommand)
+       {
+               eError = PVRSRV_ERROR_TIMEOUT;
+               goto Exit;
+       }
+
+       
+       psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl;
+
+#if defined(PDUMP)
+       
+       psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
+#endif
+
+       
+       psDevInfo->ui32CacheControl = 0;
+
+       
+       *psSGXCommand = *psCommandData;
+
+       if (eCmdType >= SGXMKIF_CMD_MAX)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM: Unknown command type: %d", eCmdType)) ;
+               eError = PVRSRV_ERROR_INVALID_CCB_COMMAND;
+               goto Exit;
+       }
+
+       
+       SysAcquireData(&psSysData);
+
+       if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+       {
+               OSFlushCPUCacheKM();
+       }
+       else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+       {
+               OSCleanCPUCacheKM();
+       }
+
+       
+       psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+
+       PVR_ASSERT(eCmdType < SGXMKIF_CMD_MAX);
+       psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType];       
+
+#if defined(PDUMP)
+       if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
+               (bPersistentProcess == IMG_FALSE) )
+       {
+               
+               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n");
+               PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+                                       offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+                                       (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff,
+                                       0xff,
+                                       PDUMP_POLL_OPERATOR_NOTEQUAL,
+                                       ui32PDumpFlags,
+                                       MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+
+               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB command (type == %d)\r\n", eCmdType);
+               pvDumpCommand = (IMG_VOID *)((IMG_UINT8 *)psKernelCCB->psCCBMemInfo->pvLinAddrKM + (*psKernelCCB->pui32WriteOffset * sizeof(SGXMKIF_COMMAND)));
+
+               PDUMPMEM(pvDumpCommand,
+                                       psKernelCCB->psCCBMemInfo,
+                                       psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND),
+                                       sizeof(SGXMKIF_COMMAND),
+                                       ui32PDumpFlags,
+                                       MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+               
+               PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
+                                       psKernelCCB->psCCBMemInfo,
+                                       psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) +
+                                       offsetof(SGXMKIF_COMMAND, ui32CacheControl),
+                                       sizeof(IMG_UINT32),
+                                       ui32PDumpFlags,
+                                       MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+               if (PDumpIsCaptureFrameKM()
+               || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+               {
+                       
+                       psDevInfo->sPDContext.ui32CacheControl = 0;
+               }
+       }
+#endif
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+       
+       eError = PollForValueKM (psKernelCCB->pui32ReadOffset,
+                                                               *psKernelCCB->pui32WriteOffset,
+                                                               0xFF,
+                                                               MAX_HW_TIME_US,
+                                                               MAX_HW_TIME_US/WAIT_TRY_COUNT,
+                                                               IMG_FALSE);
+       if (eError != PVRSRV_OK)
+       {
+               eError = PVRSRV_ERROR_TIMEOUT;
+               goto Exit;
+       }
+#endif
+
+       
+
+       *psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255;
+
+#if defined(PDUMP)
+       if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
+               (bPersistentProcess == IMG_FALSE) )
+       {
+       #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for previous Kernel CCB CMD to be read\r\n");
+               PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+                                       offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+                                       (psKernelCCB->ui32CCBDumpWOff),
+                                       0xFF,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       ui32PDumpFlags,
+                                       MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+       #endif
+
+               if (PDumpIsCaptureFrameKM()
+               || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+               {
+                       psKernelCCB->ui32CCBDumpWOff = (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
+                       psDevInfo->ui32KernelCCBEventKickerDumpVal = (psDevInfo->ui32KernelCCBEventKickerDumpVal + 1) & 0xFF;
+               }
+
+               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB write offset\r\n");
+               PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+                                psKernelCCB->psCCBCtlMemInfo,
+                                offsetof(PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
+                                sizeof(IMG_UINT32),
+                                ui32PDumpFlags,
+                                MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB event kicker\r\n");
+               PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+                                psDevInfo->psKernelCCBEventKickerMemInfo,
+                                0,
+                                sizeof(IMG_UINT32),
+                                ui32PDumpFlags,
+                                MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kick the SGX microkernel\r\n");
+       #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK, ui32PDumpFlags);
+       #else
+               PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK, ui32PDumpFlags);
+       #endif
+       }
+#endif
+
+       *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+
+       OSWriteMemoryBarrier();
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+                               SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+                               EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+                               SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+                               EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+       OSMemoryBarrier();
+
+#if defined(NO_HARDWARE)
+       
+       *psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255;
+#endif
+
+Exit:
+       return eError;
+}
+
+
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE                *psDeviceNode,
+                                                                        SGXMKIF_CMD_TYPE               eCmdType,
+                                                                        SGXMKIF_COMMAND                *psCommandData,
+                                                                        IMG_UINT32                             ui32CallerID,
+                                                                        IMG_UINT32                             ui32PDumpFlags)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+
+       
+       PDUMPSUSPEND();
+
+       eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+                                                                                PVRSRV_DEV_POWER_STATE_ON,
+                                                                                ui32CallerID,
+                                                                                IMG_TRUE);
+
+       PDUMPRESUME();
+
+       if (eError == PVRSRV_OK)
+       {
+               psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
+       }
+       else
+       {
+               if (eError == PVRSRV_ERROR_RETRY)
+               {
+                       if (ui32CallerID == ISR_ID)
+                       {
+                               
+
+
+                               psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+                               eError = PVRSRV_OK;
+                       }
+                       else
+                       {
+                               
+
+                       }
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+                                        "ui32CallerID:%d eError:%u", ui32CallerID, eError));
+               }
+
+               return eError;
+       }
+
+       eError = SGXScheduleCCBCommand(psDevInfo, eCmdType, psCommandData, ui32CallerID, ui32PDumpFlags);
+
+       PVRSRVPowerUnlock(ui32CallerID);
+
+       if (ui32CallerID != ISR_ID)
+       {
+               
+
+
+               SGXTestActivePowerEvent(psDeviceNode, ui32CallerID);
+       }
+
+       return eError;
+}
+
+
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       SGXMKIF_HOST_CTL        *psHostCtl = psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+       IMG_UINT32              ui32PowerStatus;
+       SGXMKIF_COMMAND         sCommand = {0};
+
+       ui32PowerStatus = psHostCtl->ui32PowerStatus;
+       if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+       {
+               
+               return PVRSRV_OK;
+       }
+
+       eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_PROCESS_QUEUES, &sCommand, ISR_ID, 0);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SGXScheduleProcessQueuesKM failed to schedule CCB command: %u", eError));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+                                                                       SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo)
+{
+       PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+       psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
+       psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
+
+       
+       psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
+               (IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo;
+
+       return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE  *psDeviceNode,
+                                                  IMG_DEV_VIRTADDR             *psHWDataDevVAddr,
+                                                  IMG_UINT32                   ui32CleanupType)
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_SGXDEV_INFO              *psSGXDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_KERNEL_MEM_INFO  *psSGXHostCtlMemInfo = psSGXDevInfo->psKernelSGXHostCtlMemInfo;
+       SGXMKIF_HOST_CTL                *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+
+       if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+       {
+               
+       }
+       else
+       {
+               SGXMKIF_COMMAND         sCommand = {0};
+
+               PDUMPCOMMENTWITHFLAGS(0, "Request ukernel resouce clean-up");
+               sCommand.ui32Data[0] = ui32CleanupType;
+               sCommand.ui32Data[1] = (psHWDataDevVAddr == IMG_NULL) ? 0 : psHWDataDevVAddr->uiAddr;
+
+               eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CLEANUP, &sCommand, KERNEL_ID, 0);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command"));
+                       PVR_DBG_BREAK;
+               }
+
+               
+               #if !defined(NO_HARDWARE)
+               if(PollForValueKM(&psSGXHostCtl->ui32CleanupStatus,
+                                                 PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+                                                 PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+                                                 10 * MAX_HW_TIME_US,
+                                                 1000,
+                                                 IMG_TRUE) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up (%u) failed", ui32CleanupType));
+                       PVR_DBG_BREAK;
+               }
+               #endif
+
+               #if defined(PDUMP)
+               
+               PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete");
+               PDUMPMEMPOL(psSGXHostCtlMemInfo,
+                                       offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus),
+                                       PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+                                       PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       0,
+                                       MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+               #endif 
+
+               psSGXHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE);
+               PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+               
+               
+       #if defined(SGX_FEATURE_SYSTEM_CACHE)
+               psSGXDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA);
+       #else
+               psSGXDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA;
+       #endif
+       }
+}
+
+
+typedef struct _SGX_HW_RENDER_CONTEXT_CLEANUP_
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+       IMG_HANDLE hBlockAlloc;
+       PRESMAN_ITEM psResItem;
+} SGX_HW_RENDER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWRenderContextCallback(IMG_PVOID                pvParam,
+                                                                                                         IMG_UINT32    ui32Param)
+{
+       SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       SGXCleanupRequest(psCleanup->psDeviceNode,
+                                         &psCleanup->sHWRenderContextDevVAddr,
+                                         PVRSRV_CLEANUPCMD_RC);
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+                         psCleanup,
+                         psCleanup->hBlockAlloc);
+       
+
+       return PVRSRV_OK;
+}
+
+typedef struct _SGX_HW_TRANSFER_CONTEXT_CLEANUP_
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+       IMG_HANDLE hBlockAlloc;
+       PRESMAN_ITEM psResItem;
+} SGX_HW_TRANSFER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWTransferContextCallback(IMG_PVOID      pvParam,
+                                                                                                               IMG_UINT32      ui32Param)
+{
+       SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       SGXCleanupRequest(psCleanup->psDeviceNode,
+                                         &psCleanup->sHWTransferContextDevVAddr,
+                                         PVRSRV_CLEANUPCMD_TC);
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+                         psCleanup,
+                         psCleanup->hBlockAlloc);
+       
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE                             psDeviceNode,
+                                                                               IMG_DEV_VIRTADDR                *psHWRenderContextDevVAddr,
+                                                                               PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hBlockAlloc;
+       SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+       PRESMAN_ITEM psResItem;
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+                                               (IMG_VOID **)&psCleanup,
+                                               &hBlockAlloc,
+                                               "SGX Hardware Render Context Cleanup");
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate memory for SGX_HW_RENDER_CONTEXT_CLEANUP structure"));
+               return IMG_NULL;
+       }
+
+       psCleanup->hBlockAlloc = hBlockAlloc;
+       psCleanup->psDeviceNode = psDeviceNode;
+       psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr;
+
+       psResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                 RESMAN_TYPE_HW_RENDER_CONTEXT,
+                                                                 (IMG_VOID *)psCleanup,
+                                                                 0,
+                                                                 &SGXCleanupHWRenderContextCallback);
+
+       if (psResItem == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: ResManRegisterRes failed"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+                                 psCleanup,
+                                 psCleanup->hBlockAlloc);
+               
+
+               return IMG_NULL;
+       }
+
+       psCleanup->psResItem = psResItem;
+
+       return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext)
+{
+       PVRSRV_ERROR eError;
+       SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+
+       PVR_ASSERT(hHWRenderContext != IMG_NULL);
+
+       psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+
+       if (psCleanup == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWRenderContextKM: invalid parameter"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+       return eError;
+}
+
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE                           psDeviceNode,
+                                                                                 IMG_DEV_VIRTADDR                      *psHWTransferContextDevVAddr,
+                                                                                 PVRSRV_PER_PROCESS_DATA       *psPerProc)
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hBlockAlloc;
+       SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+       PRESMAN_ITEM psResItem;
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+                                               (IMG_VOID **)&psCleanup,
+                                               &hBlockAlloc,
+                                               "SGX Hardware Transfer Context Cleanup");
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate memory for SGX_HW_TRANSFER_CONTEXT_CLEANUP structure"));
+               return IMG_NULL;
+       }
+
+       psCleanup->hBlockAlloc = hBlockAlloc;
+       psCleanup->psDeviceNode = psDeviceNode;
+       psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr;
+
+       psResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                 RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+                                                                 psCleanup,
+                                                                 0,
+                                                                 &SGXCleanupHWTransferContextCallback);
+
+       if (psResItem == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: ResManRegisterRes failed"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+                                 psCleanup,
+                                 psCleanup->hBlockAlloc);
+               
+
+               return IMG_NULL;
+       }
+
+       psCleanup->psResItem = psResItem;
+
+       return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext)
+{
+       PVRSRV_ERROR eError;
+       SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+
+       PVR_ASSERT(hHWTransferContext != IMG_NULL);
+
+       psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+       if (psCleanup == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: invalid parameter"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+       return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGX_HW_2D_CONTEXT_CLEANUP_
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+       IMG_HANDLE hBlockAlloc;
+       PRESMAN_ITEM psResItem;
+} SGX_HW_2D_CONTEXT_CLEANUP;
+
+static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+       SGX_HW_2D_CONTEXT_CLEANUP *psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       SGXCleanupRequest(psCleanup->psDeviceNode,
+                                         &psCleanup->sHW2DContextDevVAddr,
+                                         PVRSRV_CLEANUPCMD_2DC);
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+                         psCleanup,
+                         psCleanup->hBlockAlloc);
+       
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE                         psDeviceNode,
+                                                                       IMG_DEV_VIRTADDR                *psHW2DContextDevVAddr,
+                                                                       PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hBlockAlloc;
+       SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+       PRESMAN_ITEM psResItem;
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                               sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+                                               (IMG_VOID **)&psCleanup,
+                                               &hBlockAlloc,
+                                               "SGX Hardware 2D Context Cleanup");
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate memory for SGX_HW_2D_CONTEXT_CLEANUP structure"));
+               return IMG_NULL;
+       }
+
+       psCleanup->hBlockAlloc = hBlockAlloc;
+       psCleanup->psDeviceNode = psDeviceNode;
+       psCleanup->sHW2DContextDevVAddr = *psHW2DContextDevVAddr;
+
+       psResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                 RESMAN_TYPE_HW_2D_CONTEXT,
+                                                                 psCleanup,
+                                                                 0,
+                                                                 &SGXCleanupHW2DContextCallback);
+
+       if (psResItem == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: ResManRegisterRes failed"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+                                 psCleanup,
+                                 psCleanup->hBlockAlloc);
+               
+
+               return IMG_NULL;
+       }
+
+       psCleanup->psResItem = psResItem;
+
+       return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext)
+{
+       PVRSRV_ERROR eError;
+       SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+
+       PVR_ASSERT(hHW2DContext != IMG_NULL);
+
+       if (hHW2DContext == IMG_NULL)
+       {
+               return (PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)hHW2DContext;
+
+       eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+       return eError;
+}
+#endif 
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DQuerySyncOpsComplete)
+#endif
+static INLINE
+IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO     *psSyncInfo,
+                                                                  IMG_UINT32                           ui32ReadOpsPending,
+                                                                  IMG_UINT32                           ui32WriteOpsPending)
+{
+       PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+       return (IMG_BOOL)(
+                                         (psSyncData->ui32ReadOpsComplete >= ui32ReadOpsPending) &&
+                                         (psSyncData->ui32WriteOpsComplete >= ui32WriteOpsPending)
+                                        );
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO      *psDevInfo,
+                                                                          PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+                                                                          IMG_BOOL bWaitForComplete)
+{
+       IMG_UINT32      ui32ReadOpsPending, ui32WriteOpsPending;
+
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+       PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start"));
+
+       ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+       ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+       if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+       {
+               
+               PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete."));
+               return PVRSRV_OK;
+       }
+
+       
+       if (!bWaitForComplete)
+       {
+               
+               PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending."));
+               return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+       }
+
+       
+       PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling."));
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               OSSleepms(1);
+
+               if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+               {
+                       
+                       PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over.  Blits complete."));
+                       return PVRSRV_OK;
+               }
+
+               OSSleepms(1);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       
+       PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
+
+#if defined(DEBUG)
+       {
+               PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+               PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: 0x%x, Syncdata: 0x%x",
+                               (IMG_UINTPTR_T)psSyncInfo, (IMG_UINTPTR_T)psSyncData));
+
+               PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Read ops complete: %d, Read ops pending: %d", psSyncData->ui32ReadOpsComplete, psSyncData->ui32ReadOpsPending));
+               PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Write ops complete: %d, Write ops pending: %d", psSyncData->ui32WriteOpsComplete, psSyncData->ui32WriteOpsPending));
+
+       }
+#endif
+
+       return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+IMG_EXPORT
+IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psDeviceNode, IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr)
+{
+       PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr != IMG_NULL);
+
+       SGXCleanupRequest(psDeviceNode,
+                                         &sHWRTDataSetDevVAddr,
+                                         PVRSRV_CLEANUPCMD_RT);
+}
+
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO      *psDevInfo,
+                                                          IMG_UINT32                   ui32TimeWraps,
+                                                          IMG_UINT32                   ui32Time)
+{
+#if defined(EUR_CR_TIMER)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32TimeWraps);
+       return ui32Time;
+#else
+       IMG_UINT64      ui64Clocks;
+       IMG_UINT32      ui32Clocksx16;
+
+       ui64Clocks = ((IMG_UINT64)ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
+                                       (psDevInfo->ui32uKernelTimerClock - (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
+       ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16);
+
+       return ui32Clocksx16;
+#endif 
+}
+
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxutils.h b/drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxutils.h
new file mode 100644 (file)
index 0000000..bc4c053
--- /dev/null
@@ -0,0 +1,99 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "perproc.h"
+#include "sgxinfokm.h"
+
+#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
+       ((sizeof(type) <= (psCCBMemInfo)->ui32AllocSize) && \
+       ((psCCBKick)->offset <= (psCCBMemInfo)->ui32AllocSize - sizeof(type)))
+
+#define        CCB_DATA_FROM_OFFSET(type, psCCBMemInfo, psCCBKick, offset) \
+       ((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \
+               (psCCBKick)->offset))
+
+
+IMG_IMPORT
+IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE    *psDeviceNode,
+                                                                IMG_UINT32                     ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO  *psDevInfo,
+                                                                  SGXMKIF_CMD_TYPE             eCommandType,
+                                                                  SGXMKIF_COMMAND              *psCommandData,
+                                                                  IMG_UINT32                   ui32CallerID,
+                                                                  IMG_UINT32                   ui32PDumpFlags);
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE                *psDeviceNode,
+                                                                        SGXMKIF_CMD_TYPE               eCommandType,
+                                                                        SGXMKIF_COMMAND                *psCommandData,
+                                                                        IMG_UINT32                             ui32CallerID,
+                                                                        IMG_UINT32                             ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE                             psDeviceNode,
+                                                                               IMG_DEV_VIRTADDR                *psHWRenderContextDevVAddr,
+                                                                               PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE                           psDeviceNode,
+                                                                                 IMG_DEV_VIRTADDR                      *psHWTransferContextDevVAddr,
+                                                                                 PVRSRV_PER_PROCESS_DATA       *psPerProc);
+
+IMG_IMPORT
+IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psSGXDevInfo, IMG_DEV_VIRTADDR psHWRTDataSetDevVAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE                         psDeviceNode,
+                                                                       IMG_DEV_VIRTADDR                *psHW2DContextDevVAddr,
+                                                                       PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext);
+#endif
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO      *psDevInfo,
+                                                          IMG_UINT32                   ui32TimeWraps,
+                                                          IMG_UINT32                   ui32Time);
+
+IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE  *psDeviceNode,
+                                                       IMG_DEV_VIRTADDR        *psHWDataDevVAddr,
+                                                       IMG_UINT32                      ui32CleanupType);
+                                                          
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/env_data.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/env_data.h
new file mode 100644 (file)
index 0000000..3d41219
--- /dev/null
@@ -0,0 +1,66 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+#define PVRSRV_MAX_BRIDGE_IN_SIZE      0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE     0x1000
+
+typedef        struct _PVR_PCI_DEV_TAG
+{
+       struct pci_dev          *psPCIDev;
+       HOST_PCI_INIT_FLAGS     ePCIFlags;
+       IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+typedef struct _ENV_DATA_TAG
+{
+       IMG_VOID                *pvBridgeData;
+       struct pm_dev           *psPowerDevice;
+       IMG_BOOL                bLISRInstalled;
+       IMG_BOOL                bMISRInstalled;
+       IMG_UINT32              ui32IRQ;
+       IMG_VOID                *pvISRCookie;
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+       struct workqueue_struct *psWorkQueue;
+#endif
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+       struct work_struct      sMISRWork;
+       IMG_VOID                *pvMISRData;
+#else
+       struct tasklet_struct   sMISRTasklet;
+#endif
+} ENV_DATA;
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/env_perproc.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/env_perproc.h
new file mode 100644 (file)
index 0000000..a6e49db
--- /dev/null
@@ -0,0 +1,56 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+
+#include "services.h"
+#include "handle.h"
+
+typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
+{
+       IMG_HANDLE hBlockAlloc;
+       struct proc_dir_entry *psProcDir;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       struct list_head sDRMAuthListHead;
+#endif
+} PVRSRV_ENV_PER_PROCESS_DATA;
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/event.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/event.c
new file mode 100644 (file)
index 0000000..ad435a2
--- /dev/null
@@ -0,0 +1,266 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "lock.h"
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+   rwlock_t                       sLock;
+   struct list_head        sList;
+
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+       atomic_t        sTimeStamp;
+       IMG_UINT32  ui32TimeStampPrevious;
+#if defined(DEBUG)
+       IMG_UINT        ui32Stats;
+#endif
+    wait_queue_head_t sWait;
+       struct list_head        sList;
+       IMG_HANDLE                              hResItem;
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList;
+
+       if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST),
+               (IMG_VOID **)&psEvenObjectList, IMG_NULL,
+               "Linux Event Object List") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+    INIT_LIST_HEAD(&psEvenObjectList->sList);
+
+       rwlock_init(&psEvenObjectList->sLock);
+
+       *phEventObjectList = (IMG_HANDLE *) psEvenObjectList;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+       if(psEvenObjectList)
+       {
+               if (!list_empty(&psEvenObjectList->sList))
+               {
+                        PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+                        return PVRSRV_ERROR_GENERIC;
+               }
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEvenObjectList, IMG_NULL);
+
+       }
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
+{
+       if(hOSEventObjectList)
+       {
+               if(hOSEventObject)
+               {
+                       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+#if defined(DEBUG)
+                       PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %lu", psLinuxEventObject->ui32Stats));
+#endif
+                       if(ResManFreeResByPtr(psLinuxEventObject->hResItem) != PVRSRV_OK)
+                       {
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+
+                       return PVRSRV_OK;
+               }
+       }
+       return PVRSRV_ERROR_GENERIC;
+
+}
+
+static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       write_lock_bh(&psLinuxEventObjectList->sLock);
+       list_del(&psLinuxEventObject->sList);
+       write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+#if defined(DEBUG)
+       PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %lu", psLinuxEventObject->ui32Stats));
+#endif
+
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
+
+
+       return PVRSRV_OK;
+}
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+       IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+       PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+       psPerProc = PVRSRVPerProcessData(ui32PID);
+       if (psPerProc == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+
+       if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT),
+               (IMG_VOID **)&psLinuxEventObject, IMG_NULL,
+               "Linux Event Object") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+       atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+       psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+       psLinuxEventObject->ui32Stats = 0;
+#endif
+    init_waitqueue_head(&psLinuxEventObject->sWait);
+
+       psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+       psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                        RESMAN_TYPE_EVENT_OBJECT,
+                                                                                                        psLinuxEventObject,
+                                                                                                        0,
+                                                                                                        &LinuxEventObjectDeleteCallback);
+
+       write_lock_bh(&psLinuxEventObjectList->sLock);
+       list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+    write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+       *phOSEventObject = psLinuxEventObject;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+       struct list_head *psListEntry, *psListEntryTemp, *psList;
+       psList = &psLinuxEventObjectList->sList;
+
+       list_for_each_safe(psListEntry, psListEntryTemp, psList)
+       {
+
+               psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);
+
+               atomic_inc(&psLinuxEventObject->sTimeStamp);
+               wake_up_interruptible(&psLinuxEventObject->sWait);
+       }
+
+       return  PVRSRV_OK;
+
+}
+
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+       IMG_UINT32 ui32TimeStamp;
+       DEFINE_WAIT(sWait);
+
+       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+       IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+
+       do
+       {
+               prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+               ui32TimeStamp = atomic_read(&psLinuxEventObject->sTimeStamp);
+
+               if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+               {
+                       break;
+               }
+
+               mutex_unlock(&gPVRSRVLock);
+
+               ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+
+               mutex_lock(&gPVRSRVLock);
+#if defined(DEBUG)
+               psLinuxEventObject->ui32Stats++;
+#endif
+
+
+       } while (ui32TimeOutJiffies);
+
+       finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+       psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+       return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/event.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/event.h
new file mode 100644 (file)
index 0000000..d07bc97
--- /dev/null
@@ -0,0 +1,32 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/linkage.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/linkage.h
new file mode 100644 (file)
index 0000000..1ec2696
--- /dev/null
@@ -0,0 +1,61 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __LINKAGE_H__
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRI_DRM)
+IMG_INT32 PVRSRV_BridgeDispatchKM(struct file *file, IMG_UINT cmd, IMG_UINT32 arg);
+#endif
+
+IMG_VOID PVRDPFInit(IMG_VOID);
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID);
+IMG_VOID PVROSFuncDeInit(IMG_VOID);
+
+#ifdef DEBUG
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+IMG_VOID PVRDebugSetLevel(IMG_UINT32 uDebugLevel);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el);
+#else
+IMG_INT PVRDebugProcGetLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
+#else
+IMG_INT PVRProcGetPowerLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+
+#endif
+#endif
+
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/lock.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/lock.h
new file mode 100644 (file)
index 0000000..b9b5cf0
--- /dev/null
@@ -0,0 +1,34 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __LOCK_H__
+#define __LOCK_H__
+
+#include <linux/mutex.h>
+
+extern struct mutex gPVRSRVLock;
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mm.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mm.c
new file mode 100644 (file)
index 0000000..241a1aa
--- /dev/null
@@ -0,0 +1,570 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "syscommon.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "lock.h"
+
+
+static struct kmem_cache *linux_mem_area_cache;
+
+int linux_mm_init(void)
+{
+       linux_mem_area_cache = kmem_cache_create("img-mm", sizeof(LinuxMemArea), 0, 0, NULL);
+
+       if (!linux_mem_area_cache)
+       {
+               pr_err("%s: failed to allocate kmem_cache", __FUNCTION__);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+void linux_mm_cleanup(void)
+{
+       if (linux_mem_area_cache)
+       {
+               kmem_cache_destroy(linux_mem_area_cache);
+               linux_mem_area_cache = NULL;
+       }
+}
+
+void *vmalloc_wrapper(u32 bytes, u32 alloc_flags)
+{
+       /*
+        * FIXME: This function creates a memory alias
+        * of a page, with a mismatching PAT type.
+        * This wants to be fixed most likely.
+        */
+       pgprot_t pgprot_flags;
+
+       switch(alloc_flags & PVRSRV_HAP_CACHETYPE_MASK)
+       {
+       case PVRSRV_HAP_CACHED:
+               pgprot_flags = PAGE_KERNEL;
+               break;
+       case PVRSRV_HAP_WRITECOMBINE:
+               pgprot_flags = PGPROT_WC(PAGE_KERNEL);
+               break;
+       case PVRSRV_HAP_UNCACHED:
+               pgprot_flags = PGPROT_UC(PAGE_KERNEL);
+               break;
+       default:
+               WARN(1, "unknown mapping flags=0x%08x", alloc_flags);
+               return NULL;
+       }
+
+
+       return __vmalloc(bytes, GFP_KERNEL | __GFP_HIGHMEM, pgprot_flags);
+}
+
+LinuxMemArea *vmalloc_linux_mem_area(u32 bytes, u32 area_flags)
+{
+       LinuxMemArea *mem_area;
+       void *vptr;
+
+       mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+
+       if (!mem_area)
+               goto failed;
+
+       vptr = vmalloc_wrapper(bytes, area_flags);
+       if (!vptr)
+               goto failed;
+
+       mem_area->eAreaType = LINUX_MEM_AREA_VMALLOC;
+       mem_area->uData.sVmalloc.pvVmallocAddress = vptr;
+       mem_area->ui32ByteSize = bytes;
+       mem_area->ui32AreaFlags = area_flags;
+       mem_area->bMMapRegistered = IMG_FALSE;
+       INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+       return mem_area;
+
+failed:
+       pr_err("%s: failed!", __FUNCTION__);
+       if (mem_area)
+               kmem_cache_free(linux_mem_area_cache, mem_area);
+       return NULL;
+}
+
+
+void __iomem *ioremap_wrapper(resource_size_t address,
+               u32 bytes, u32 mapping_flags)
+{
+       void __iomem *cookie;
+
+       switch(mapping_flags & PVRSRV_HAP_CACHETYPE_MASK)
+       {
+        case PVRSRV_HAP_CACHED:
+               cookie = ioremap_cache(address, bytes);
+               break;
+       case PVRSRV_HAP_WRITECOMBINE:
+               cookie = ioremap_wc(address, bytes);
+               break;
+       case PVRSRV_HAP_UNCACHED:
+               cookie = ioremap_nocache(address, bytes);
+               break;
+        default:
+               pr_err("ioremap_wrapper: unknown mapping flags");
+               return NULL;
+       }
+
+       return cookie;
+}
+
+LinuxMemArea *
+ioremap_linux_mem_area(resource_size_t address, u32 bytes, u32 area_flags)
+{
+       LinuxMemArea *mem_area;
+       void __iomem *cookie;
+
+       mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+       if (!mem_area)
+               return NULL;
+
+       cookie = ioremap_wrapper(address, bytes, area_flags);
+       if (!cookie)
+       {
+               kmem_cache_free(linux_mem_area_cache, mem_area);
+               return NULL;
+       }
+
+       mem_area->eAreaType = LINUX_MEM_AREA_IOREMAP;
+       mem_area->uData.sIORemap.pvIORemapCookie = cookie;
+       mem_area->uData.sIORemap.CPUPhysAddr = address;
+       mem_area->ui32ByteSize = bytes;
+       mem_area->ui32AreaFlags = area_flags;
+       mem_area->bMMapRegistered = IMG_FALSE;
+       INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+       return mem_area;
+}
+
+
+static IMG_BOOL
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, u32 ui32Bytes, IMG_BOOL bPhysContig)
+{
+       u32 ui32;
+       u32 ui32AddrChk;
+       u32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+       for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+               ui32 < ui32NumPages;
+               ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
+       {
+               if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
+               {
+                       break;
+               }
+       }
+       if (ui32 == ui32NumPages)
+       {
+               return IMG_FALSE;
+       }
+
+       if (!bPhysContig)
+       {
+               for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+                       ui32 < ui32NumPages;
+                       ui32++, ui32AddrChk += PAGE_SIZE)
+               {
+                       if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+                       {
+                               return IMG_FALSE;
+                       }
+               }
+       }
+
+       return IMG_TRUE;
+}
+
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, void *pvCPUVAddr, u32 bytes, IMG_BOOL bPhysContig, u32 area_flags)
+{
+       LinuxMemArea *mem_area;
+
+       mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+
+       if (!mem_area)
+               return NULL;
+
+       mem_area->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+       mem_area->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+       mem_area->uData.sExternalKV.bPhysContig = (IMG_BOOL)(bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, bytes, bPhysContig));
+
+       if (mem_area->uData.sExternalKV.bPhysContig)
+               mem_area->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
+       else
+               mem_area->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
+
+       mem_area->ui32ByteSize = bytes;
+       mem_area->ui32AreaFlags = area_flags;
+       mem_area->bMMapRegistered = IMG_FALSE;
+       INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+       return mem_area;
+}
+
+LinuxMemArea *
+NewIOLinuxMemArea(resource_size_t address, u32 bytes, u32 area_flags)
+{
+       LinuxMemArea *mem_area;
+
+       mem_area  = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+
+       if (!mem_area)
+               return NULL;
+
+       mem_area->eAreaType = LINUX_MEM_AREA_IO;
+       mem_area->uData.sIO.CPUPhysAddr = address;
+       mem_area->ui32ByteSize = bytes;
+       mem_area->ui32AreaFlags = area_flags;
+       mem_area->bMMapRegistered = IMG_FALSE;
+       INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+       return mem_area;
+}
+
+
+LinuxMemArea * alloc_pages_linux_mem_area(u32 bytes, u32 area_flags)
+{
+       LinuxMemArea *mem_area;
+       int page_count;
+       struct page **page_list;
+       IMG_HANDLE hBlockPageList;
+       int i;
+       PVRSRV_ERROR eError;
+
+       mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+       if (!mem_area)
+               goto failed_area_alloc;
+
+
+       page_count =  RANGE_TO_PAGES(bytes);
+
+       eError = OSAllocMem(0, sizeof(*page_list) * page_count, (void **)&page_list, &hBlockPageList,
+                                                       "Array of pages");
+
+       if(eError != PVRSRV_OK)
+               goto failed_page_list_alloc;
+
+       for(i=0; i<page_count; i++)
+       {
+               page_list[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+               if(!page_list[i])
+                       goto failed_alloc_pages;
+       }
+
+       mem_area->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+       mem_area->uData.sPageList.pvPageList = page_list;
+       mem_area->uData.sPageList.hBlockPageList = hBlockPageList;
+       mem_area->ui32ByteSize = bytes;
+       mem_area->ui32AreaFlags = area_flags;
+       mem_area->bMMapRegistered = IMG_FALSE;
+       INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+       return mem_area;
+
+failed_alloc_pages:
+       for(i--; i >= 0; i--)
+               __free_pages(page_list[i], 0);
+
+       OSFreeMem(0, sizeof(*page_list) * page_count, page_list, hBlockPageList);
+       mem_area->uData.sPageList.pvPageList = NULL;
+failed_page_list_alloc:
+       kmem_cache_free(linux_mem_area_cache, mem_area);
+failed_area_alloc:
+       pr_debug("%s: failed", __FUNCTION__);
+
+       return NULL;
+}
+
+
+void free_pages_linux_mem_area(LinuxMemArea *mem_area)
+{
+       u32 page_count;
+       struct page **page_list;
+       IMG_HANDLE hBlockPageList;
+       int i;
+
+       BUG_ON(!mem_area);
+
+
+       page_count = RANGE_TO_PAGES(mem_area->ui32ByteSize);
+       page_list = mem_area->uData.sPageList.pvPageList;
+       hBlockPageList = mem_area->uData.sPageList.hBlockPageList;
+
+       for(i = 0; i < page_count; i++)
+               __free_pages(page_list[i], 0);
+
+
+       OSFreeMem(0, sizeof(*page_list) * page_count, page_list, hBlockPageList);
+       mem_area->uData.sPageList.pvPageList = NULL;
+}
+
+
+struct page* LinuxMemAreaOffsetToPage(LinuxMemArea *mem_area, u32 offset)
+{
+       u32 page_index;
+       u8 *addr;
+
+       switch(mem_area->eAreaType)
+       {
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+               page_index = PHYS_TO_PFN(offset);
+               return mem_area->uData.sPageList.pvPageList[page_index];
+
+        case LINUX_MEM_AREA_VMALLOC:
+               addr = mem_area->uData.sVmalloc.pvVmallocAddress;
+               addr += offset;
+               return vmalloc_to_page(addr);
+
+        case LINUX_MEM_AREA_SUB_ALLOC:
+               return LinuxMemAreaOffsetToPage(mem_area->uData.sSubAlloc.psParentLinuxMemArea,
+                                            mem_area->uData.sSubAlloc.ui32ByteOffset
+                                             + offset);
+        default:
+               pr_err("%s: Unsupported request for struct page from LinuxMemArea with type=%s",
+                    __FUNCTION__, LinuxMemAreaTypeToString(mem_area->eAreaType));
+               return NULL;
+       }
+}
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *parent, u32 offset, u32 bytes)
+{
+       LinuxMemArea *mem_area;
+
+       BUG_ON(offset+bytes > parent->ui32ByteSize);
+
+       mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+       if (!mem_area)
+               return NULL;
+
+       mem_area->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+       mem_area->uData.sSubAlloc.psParentLinuxMemArea = parent;
+       mem_area->uData.sSubAlloc.ui32ByteOffset = offset;
+       mem_area->ui32ByteSize = bytes;
+       mem_area->ui32AreaFlags = parent->ui32AreaFlags;
+       mem_area->bMMapRegistered = IMG_FALSE;
+       INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+       return mem_area;
+}
+
+
+void LinuxMemAreaDeepFree(LinuxMemArea *mem_area)
+{
+       /* FIXME: call vfree and co direct, and free the mem area centrally at the end */
+       switch(mem_area->eAreaType)
+       {
+        case LINUX_MEM_AREA_VMALLOC:
+               vfree(mem_area->uData.sVmalloc.pvVmallocAddress);
+               break;
+       case LINUX_MEM_AREA_ALLOC_PAGES:
+               free_pages_linux_mem_area(mem_area);
+               break;
+       case LINUX_MEM_AREA_IOREMAP:
+               iounmap(mem_area->uData.sIORemap.pvIORemapCookie);
+               break;
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+       case LINUX_MEM_AREA_IO:
+       case LINUX_MEM_AREA_SUB_ALLOC:
+               break;
+        default:
+               pr_debug("%s: Unknown are type (%d)\n",
+                     __FUNCTION__, mem_area->eAreaType);
+               break;
+       }
+       kmem_cache_free(linux_mem_area_cache, mem_area);
+}
+
+
+void * LinuxMemAreaToCpuVAddr(LinuxMemArea *mem_area)
+{
+       switch(mem_area->eAreaType)
+       {
+        case LINUX_MEM_AREA_VMALLOC:
+               return mem_area->uData.sVmalloc.pvVmallocAddress;
+        case LINUX_MEM_AREA_IOREMAP:
+               return mem_area->uData.sIORemap.pvIORemapCookie;
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+               return mem_area->uData.sExternalKV.pvExternalKV;
+        case LINUX_MEM_AREA_SUB_ALLOC:
+        {
+               char *addr = LinuxMemAreaToCpuVAddr(mem_area->uData.sSubAlloc.psParentLinuxMemArea);
+               if (!addr)
+                       return NULL;
+               return addr + mem_area->uData.sSubAlloc.ui32ByteOffset;
+        }
+        default:
+               return NULL;
+       }
+}
+
+
+resource_size_t LinuxMemAreaToCpuPAddr(LinuxMemArea *mem_area, u32 offset)
+{
+       resource_size_t address;
+
+       address = 0;
+
+       switch(mem_area->eAreaType)
+       {
+        case LINUX_MEM_AREA_IOREMAP:
+        {
+               address = mem_area->uData.sIORemap.CPUPhysAddr;
+               address += offset;
+               break;
+        }
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+       {
+               if (mem_area->uData.sExternalKV.bPhysContig)
+               {
+                       IMG_CPU_PHYADDR CpuPAddr = SysSysPAddrToCpuPAddr(mem_area->uData.sExternalKV.uPhysAddr.SysPhysAddr);
+                       address = CpuPAddr.uiAddr + offset;
+               } else {
+                       u32 page_index = PHYS_TO_PFN(offset);
+                       IMG_SYS_PHYADDR SysPAddr = mem_area->uData.sExternalKV.uPhysAddr.pSysPhysAddr[page_index];
+                       IMG_CPU_PHYADDR CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+                       address = CpuPAddr.uiAddr + ADDR_TO_PAGE_OFFSET(offset);
+               }
+               break;
+       }
+        case LINUX_MEM_AREA_IO:
+        {
+               address = mem_area->uData.sIO.CPUPhysAddr;
+               address += offset;
+               break;
+        }
+        case LINUX_MEM_AREA_VMALLOC:
+        {
+               char *vaddr;
+               vaddr = mem_area->uData.sVmalloc.pvVmallocAddress;
+               vaddr += offset;
+               address = VMallocToPhys(vaddr);
+               break;
+        }
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+        {
+               struct page *page;
+               u32 page_index = PHYS_TO_PFN(offset);
+               page = mem_area->uData.sPageList.pvPageList[page_index];
+               address = page_to_phys(page);
+               address += ADDR_TO_PAGE_OFFSET(offset);
+               break;
+        }
+        case LINUX_MEM_AREA_SUB_ALLOC:
+        {
+               IMG_CPU_PHYADDR  CpuPAddr =
+                   OSMemHandleToCpuPAddr(mem_area->uData.sSubAlloc.psParentLinuxMemArea,
+                                      mem_area->uData.sSubAlloc.ui32ByteOffset
+                                        + offset);
+
+               address = CpuPAddr.uiAddr;
+               break;
+        }
+        default:
+               pr_debug("%s: Unknown LinuxMemArea type (%d)\n",
+                     __FUNCTION__, mem_area->eAreaType);
+               break;
+       }
+
+       BUG_ON(!address);
+       return address;
+}
+
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *mem_area)
+{
+       switch(mem_area->eAreaType)
+       {
+       case LINUX_MEM_AREA_IOREMAP:
+       case LINUX_MEM_AREA_IO:
+               return IMG_TRUE;
+
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+               return mem_area->uData.sExternalKV.bPhysContig;
+
+        case LINUX_MEM_AREA_VMALLOC:
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+               return IMG_FALSE;
+
+        case LINUX_MEM_AREA_SUB_ALLOC:
+
+               return LinuxMemAreaPhysIsContig(mem_area->uData.sSubAlloc.psParentLinuxMemArea);
+
+        default:
+               pr_debug("%s: Unknown LinuxMemArea type (%d)\n",
+                     __FUNCTION__, mem_area->eAreaType);
+               break;
+       }
+       return IMG_FALSE;
+}
+
+
+const char *
+LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+
+       switch(eMemAreaType)
+       {
+        case LINUX_MEM_AREA_IOREMAP:
+               return "LINUX_MEM_AREA_IOREMAP";
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+               return "LINUX_MEM_AREA_EXTERNAL_KV";
+        case LINUX_MEM_AREA_IO:
+               return "LINUX_MEM_AREA_IO";
+        case LINUX_MEM_AREA_VMALLOC:
+               return "LINUX_MEM_AREA_VMALLOC";
+        case LINUX_MEM_AREA_SUB_ALLOC:
+               return "LINUX_MEM_AREA_SUB_ALLOC";
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+               return "LINUX_MEM_AREA_ALLOC_PAGES";
+        default:
+               BUG();
+       }
+
+       return "";
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mm.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mm.h
new file mode 100644 (file)
index 0000000..13ca102
--- /dev/null
@@ -0,0 +1,198 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#define        PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define        ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+static inline u32 VMallocToPhys(void *pCpuVAddr)
+{
+       return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
+               
+}
+
+typedef enum {
+    LINUX_MEM_AREA_IOREMAP,
+       LINUX_MEM_AREA_EXTERNAL_KV,
+    LINUX_MEM_AREA_IO,
+    LINUX_MEM_AREA_VMALLOC,
+    LINUX_MEM_AREA_ALLOC_PAGES,
+    LINUX_MEM_AREA_SUB_ALLOC,
+    LINUX_MEM_AREA_TYPE_COUNT
+}LINUX_MEM_AREA_TYPE;
+
+typedef struct _LinuxMemArea LinuxMemArea;
+
+
+struct _LinuxMemArea {
+    LINUX_MEM_AREA_TYPE eAreaType;
+    union _uData
+    {
+        struct _sIORemap
+        {
+            
+            resource_size_t CPUPhysAddr;
+            void *pvIORemapCookie;
+        }sIORemap;
+        struct _sExternalKV
+        {
+            
+           IMG_BOOL bPhysContig;
+           union {
+                   
+                   IMG_SYS_PHYADDR SysPhysAddr;
+                   IMG_SYS_PHYADDR *pSysPhysAddr;
+           } uPhysAddr;
+            void *pvExternalKV;
+        }sExternalKV;
+        struct _sIO
+        {
+            resource_size_t CPUPhysAddr;
+        }sIO;
+        struct _sVmalloc
+        {
+            
+            void *pvVmallocAddress;
+        }sVmalloc;
+        struct _sPageList
+        {
+            
+            struct page **pvPageList;
+           IMG_HANDLE hBlockPageList;
+        }sPageList;
+        struct _sSubAlloc
+        {
+            
+            LinuxMemArea *psParentLinuxMemArea;
+            u32 ui32ByteOffset;
+        }sSubAlloc;
+    }uData;
+
+    u32 ui32ByteSize;          
+
+    u32 ui32AreaFlags;         
+
+    IMG_BOOL bMMapRegistered;          
+
+    
+    struct list_head   sMMapItem;
+
+    
+    struct list_head   sMMapOffsetStructList;
+};
+
+int linux_mm_init(void);
+
+
+void linux_mm_cleanup(void);
+
+void *vmalloc_wrapper(u32 bytes, u32 alloc_flags);
+
+LinuxMemArea *vmalloc_linux_mem_area(u32 bytes, u32 area_flags);
+
+
+void *ioremap_wrapper(resource_size_t address, u32 bytes, u32 mapping_flags);
+
+
+LinuxMemArea *ioremap_linux_mem_area(resource_size_t address, u32 bytes, u32 area_flags);
+
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, void *pvCPUVAddr, u32 ui32Bytes, IMG_BOOL bPhysContig, u32 ui32AreaFlags);
+
+
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, u32 ui32ByteOffset);
+
+
+LinuxMemArea *NewIOLinuxMemArea(resource_size_t address, u32 ui32Bytes, u32 ui32AreaFlags);
+
+
+LinuxMemArea *alloc_pages_linux_mem_area(u32 ui32Bytes, u32 ui32AreaFlags);
+
+
+void free_pages_linux_mem_area(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+                                 u32 ui32ByteOffset,
+                                 u32 ui32Bytes);
+
+
+void LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+
+
+void *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+
+
+resource_size_t LinuxMemAreaToCpuPAddr(LinuxMemArea *mem_area, u32 offset);
+
+
+#define         LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset))
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+
+static inline LinuxMemArea *
+LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
+{
+    if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+    }
+    else
+    {
+        return psLinuxMemArea;
+    }
+}
+
+
+static inline LINUX_MEM_AREA_TYPE
+LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
+{
+    return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+
+const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+
+
+#if defined(DEBUG)
+const IMG_CHAR *HAPFlagsToString(u32 ui32Flags);
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mmap.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mmap.c
new file mode 100644 (file)
index 0000000..7ddf739
--- /dev/null
@@ -0,0 +1,840 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "proc.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+static struct mutex g_sMMapMutex;
+
+static struct kmem_cache *g_psMemmapCache = NULL;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+
+
+#define        FIRST_PHYSICAL_PFN      0
+#define        LAST_PHYSICAL_PFN       0x7fffffffUL
+#define        FIRST_SPECIAL_PFN       (LAST_PHYSICAL_PFN + 1)
+#define        LAST_SPECIAL_PFN        0xffffffffUL
+
+#define        MAX_MMAP_HANDLE         0x7fffffffUL
+
+static inline IMG_BOOL
+PFNIsPhysical(IMG_UINT32 pfn)
+{
+
+       return ((pfn >= FIRST_PHYSICAL_PFN) && (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_BOOL
+PFNIsSpecial(IMG_UINT32 pfn)
+{
+
+       return ((pfn >= FIRST_SPECIAL_PFN) && (pfn <= LAST_SPECIAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_HANDLE
+MMapOffsetToHandle(IMG_UINT32 pfn)
+{
+       if (PFNIsPhysical(pfn))
+       {
+               PVR_ASSERT(PFNIsPhysical(pfn));
+               return IMG_NULL;
+       }
+
+       return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
+}
+
+static inline IMG_UINT32
+HandleToMMapOffset(IMG_HANDLE hHandle)
+{
+       IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
+
+       if (PFNIsSpecial(ulHandle))
+       {
+               PVR_ASSERT(PFNIsSpecial(ulHandle));
+               return 0;
+       }
+
+       return ulHandle + FIRST_SPECIAL_PFN;
+}
+
+static inline IMG_BOOL
+LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
+{
+    return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+
+static inline IMG_UINT32
+GetCurrentThreadID(IMG_VOID)
+{
+       return (IMG_UINT32)current->pid;
+}
+
+static PKV_OFFSET_STRUCT
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+#if defined(DEBUG)
+    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+#if defined(DEBUG)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8lx)",
+             __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+    psOffsetStruct = kmem_cache_alloc(g_psMemmapCache, GFP_KERNEL);
+    if(psOffsetStruct == IMG_NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+        return IMG_NULL;
+    }
+
+    psOffsetStruct->ui32MMapOffset = ui32Offset;
+
+    psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+    psOffsetStruct->ui32Mapped = 0;
+
+    psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+
+
+    psOffsetStruct->ui32TID = GetCurrentThreadID();
+
+    psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+
+    psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+    psOffsetStruct->ui32RefCount = 0;
+
+    psOffsetStruct->ui32UserVAddr = 0;
+
+    list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
+
+    return psOffsetStruct;
+}
+
+
+static IMG_VOID
+DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+    list_del(&psOffsetStruct->sAreaItem);
+
+    if (psOffsetStruct->bOnMMapList)
+    {
+        list_del(&psOffsetStruct->sMMapItem);
+    }
+
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+             "psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0)));
+
+    kmem_cache_free(g_psMemmapCache, psOffsetStruct);
+}
+
+
+static inline IMG_VOID
+DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
+                               IMG_UINT32 *pui32RealByteSize,
+                               IMG_UINT32 *pui32ByteOffset)
+{
+    IMG_UINT32 ui32PageAlignmentOffset;
+    IMG_CPU_PHYADDR CpuPAddr;
+
+    CpuPAddr.uiAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+    ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+
+    *pui32ByteOffset = ui32PageAlignmentOffset;
+
+    *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+
+PVRSRV_ERROR
+PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                               IMG_HANDLE hMHandle,
+                                IMG_UINT32 *pui32MMapOffset,
+                                IMG_UINT32 *pui32ByteOffset,
+                                IMG_UINT32 *pui32RealByteSize,
+                               IMG_UINT32 *pui32UserVAddr)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_HANDLE hOSMemHandle;
+    PVRSRV_ERROR eError;
+
+    mutex_lock(&g_sMMapMutex);
+
+    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+    if (eError != PVRSRV_OK)
+    {
+       PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
+
+       goto exit_unlock;
+    }
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+                                   pui32RealByteSize,
+                                   pui32ByteOffset);
+
+
+    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+        if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
+        {
+
+          PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+
+          *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+          *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+          psOffsetStruct->ui32RefCount++;
+
+          eError = PVRSRV_OK;
+          goto exit_unlock;
+        }
+    }
+
+
+    *pui32UserVAddr = 0;
+
+    if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
+    {
+        *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+        PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+    }
+    else
+    {
+        *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+        PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+    }
+
+    psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
+    if (psOffsetStruct == IMG_NULL)
+    {
+        eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+       goto exit_unlock;
+    }
+
+
+    list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+
+    psOffsetStruct->bOnMMapList = IMG_TRUE;
+
+    psOffsetStruct->ui32RefCount++;
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    mutex_unlock(&g_sMMapMutex);
+
+    return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                               IMG_HANDLE hMHandle,
+                               IMG_BOOL *pbMUnmap,
+                               IMG_UINT32 *pui32RealByteSize,
+                                IMG_UINT32 *pui32UserVAddr)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_HANDLE hOSMemHandle;
+    PVRSRV_ERROR eError;
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    mutex_lock(&g_sMMapMutex);
+
+    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+    if (eError != PVRSRV_OK)
+    {
+       PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
+
+       goto exit_unlock;
+    }
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+
+    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+        if (psOffsetStruct->ui32PID == ui32PID)
+        {
+           if (psOffsetStruct->ui32RefCount == 0)
+           {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area 0x%p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
+               eError = PVRSRV_ERROR_GENERIC;
+               goto exit_unlock;
+           }
+
+           psOffsetStruct->ui32RefCount--;
+
+           *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
+
+           *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
+           *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+
+           eError = PVRSRV_OK;
+           goto exit_unlock;
+        }
+    }
+
+
+    PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle 0x%lx (memory area 0x%p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+
+    eError =  PVRSRV_ERROR_GENERIC;
+
+exit_unlock:
+    mutex_unlock(&g_sMMapMutex);
+
+    return eError;
+}
+
+static inline PKV_OFFSET_STRUCT
+FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_UINT32 ui32TID = GetCurrentThreadID();
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+    {
+        if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
+        {
+
+           if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
+           {
+               return psOffsetStruct;
+           }
+        }
+    }
+
+    return IMG_NULL;
+}
+
+
+static IMG_BOOL
+DoMapToUser(LinuxMemArea *psLinuxMemArea,
+            struct vm_area_struct* ps_vma,
+            IMG_UINT32 ui32ByteOffset)
+{
+    IMG_UINT32 ui32ByteSize;
+
+    if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
+                    ps_vma,
+                    psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
+    }
+
+
+    ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+    PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+#if defined (__sparc__)
+
+#error "SPARC not supported"
+#endif
+
+    if (PFNIsPhysical(ps_vma->vm_pgoff))
+    {
+       IMG_INT result;
+
+       PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+       PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
+
+
+       result = io_remap_pfn_range(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
+
+        if(result == 0)
+        {
+            return IMG_TRUE;
+        }
+
+        PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
+    }
+
+    {
+
+        IMG_UINT32 ulVMAPos;
+       IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+       IMG_UINT32 ui32PA;
+
+
+       for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+       {
+           IMG_UINT32 pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+           if (!pfn_valid(pfn))
+           {
+                PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%lx", __FUNCTION__, pfn));
+                return IMG_FALSE;
+           }
+       }
+
+
+        ulVMAPos = ps_vma->vm_start;
+       for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+       {
+           IMG_UINT32 pfn;
+           struct page *psPage;
+           IMG_INT result;
+
+           pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+           PVR_ASSERT(pfn_valid(pfn));
+
+           psPage = pfn_to_page(pfn);
+
+           result = vm_insert_page(ps_vma,  ulVMAPos, psPage);
+            if(result != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_page failed (%d)", __FUNCTION__, result));
+                return IMG_FALSE;
+            }
+            ulVMAPos += PAGE_SIZE;
+        }
+    }
+
+    return IMG_TRUE;
+}
+
+
+static IMG_VOID
+MMapVOpenNoLock(struct vm_area_struct* ps_vma)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+    PVR_ASSERT(psOffsetStruct != IMG_NULL)
+    psOffsetStruct->ui32Mapped++;
+    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+    if (psOffsetStruct->ui32Mapped > 1)
+    {
+       PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %lu)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
+        PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+    }
+
+}
+
+
+static void
+MMapVOpen(struct vm_area_struct* ps_vma)
+{
+    mutex_lock(&g_sMMapMutex);
+
+    MMapVOpenNoLock(ps_vma);
+
+    mutex_unlock(&g_sMMapMutex);
+}
+
+
+static IMG_VOID
+MMapVCloseNoLock(struct vm_area_struct* ps_vma)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+    PVR_ASSERT(psOffsetStruct != IMG_NULL)
+
+    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+    psOffsetStruct->ui32Mapped--;
+    if (psOffsetStruct->ui32Mapped == 0)
+    {
+       if (psOffsetStruct->ui32RefCount != 0)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct 0x%p has non-zero reference count (ui32RefCount = %lu). User mode address of start of mapping: 0x%lx", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
+       }
+
+       DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    ps_vma->vm_private_data = NULL;
+
+}
+
+static void
+MMapVClose(struct vm_area_struct* ps_vma)
+{
+    mutex_lock(&g_sMMapMutex);
+
+    MMapVCloseNoLock(ps_vma);
+
+    mutex_unlock(&g_sMMapMutex);
+}
+
+
+static struct vm_operations_struct MMapIOOps =
+{
+       .open=MMapVOpen,
+       .close=MMapVClose
+};
+
+
+int
+PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+    IMG_UINT32 ui32ByteSize;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    int iRetVal = 0;
+
+    PVR_UNREFERENCED_PARAMETER(pFile);
+
+    mutex_lock(&g_sMMapMutex);
+
+    ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
+                              " and ui32ByteSize %ld(0x%08lx)",
+            __FUNCTION__,
+            ps_vma->vm_pgoff,
+            ui32ByteSize, ui32ByteSize));
+
+    psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+    if (psOffsetStruct == IMG_NULL)
+    {
+#if defined(SUPPORT_DRI_DRM)
+        mutex_unlock(&g_sMMapMutex);
+
+
+        return drm_mmap(pFile, ps_vma);
+#else
+        PVR_UNREFERENCED_PARAMETER(pFile);
+
+        PVR_DPF((PVR_DBG_ERROR,
+             "%s: Attempted to mmap unregistered area at vm_pgoff %ld",
+             __FUNCTION__, ps_vma->vm_pgoff));
+        iRetVal = -EINVAL;
+#endif
+        goto unlock_and_return;
+    }
+    list_del(&psOffsetStruct->sMMapItem);
+    psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+
+    if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+        ((ps_vma->vm_flags & VM_SHARED) == 0))
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
+        iRetVal = -EINVAL;
+        goto unlock_and_return;
+    }
+
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+         __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+
+    ps_vma->vm_flags |= VM_RESERVED;
+    ps_vma->vm_flags |= VM_IO;
+
+
+    ps_vma->vm_flags |= VM_DONTEXPAND;
+
+
+    ps_vma->vm_flags |= VM_DONTCOPY;
+
+    ps_vma->vm_private_data = (void *)psOffsetStruct;
+
+    switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+           ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
+           iRetVal = -EINVAL;
+           goto unlock_and_return;
+    }
+
+
+    ps_vma->vm_ops = &MMapIOOps;
+
+    if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+    {
+        iRetVal = -EAGAIN;
+        goto unlock_and_return;
+    }
+
+    PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
+
+    psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+
+
+    MMapVOpenNoLock(ps_vma);
+
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+             __FUNCTION__, ps_vma->vm_pgoff));
+
+unlock_and_return:
+    if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
+    {
+       DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    mutex_unlock(&g_sMMapMutex);
+
+    return iRetVal;
+}
+
+
+
+
+PVRSRV_ERROR
+PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVRSRV_ERROR eError;
+#if defined(DEBUG)
+    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+    mutex_lock(&g_sMMapMutex);
+
+#if defined(DEBUG)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8lx)",
+             __FUNCTION__, pszName, psLinuxMemArea,  psLinuxMemArea->ui32AreaFlags));
+#endif
+
+    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+
+    if(psLinuxMemArea->bMMapRegistered)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
+                __FUNCTION__, psLinuxMemArea));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+       goto exit_unlock;
+    }
+
+    list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+    psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    mutex_unlock(&g_sMMapMutex);
+
+    return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVRSRV_ERROR eError;
+    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+
+    mutex_lock(&g_sMMapMutex);
+
+    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+       if (psOffsetStruct->ui32Mapped != 0)
+       {
+            PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %lu",  __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+               eError = PVRSRV_ERROR_GENERIC;
+               goto exit_unlock;
+       }
+       else
+       {
+
+            PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped",  __FUNCTION__, psOffsetStruct));
+       }
+
+       PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
+
+       DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    list_del(&psLinuxMemArea->sMMapItem);
+
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    mutex_unlock(&g_sMMapMutex);
+    return eError;
+}
+
+
+PVRSRV_ERROR
+LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+    return PVRSRV_OK;
+}
+
+IMG_VOID
+LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+    IMG_BOOL bWarn = IMG_FALSE;
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+    mutex_lock(&g_sMMapMutex);
+
+    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+    {
+       if (psOffsetStruct->ui32PID == ui32PID)
+       {
+           if (!bWarn)
+           {
+               PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
+               bWarn = IMG_TRUE;
+           }
+           PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+           PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+           DestroyOffsetStruct(psOffsetStruct);
+       }
+    }
+
+    mutex_unlock(&g_sMMapMutex);
+}
+
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+    PVRSRV_ERROR eError;
+
+    eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+    if (eError != PVRSRV_OK)
+    {
+       PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
+       return eError;
+    }
+
+    return eError;
+}
+
+
+IMG_VOID
+PVRMMapInit(IMG_VOID)
+{
+    mutex_init(&g_sMMapMutex);
+
+    g_psMemmapCache = kmem_cache_create("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0, NULL);
+    if (!g_psMemmapCache)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+       goto error;
+    }
+
+    return;
+
+error:
+    PVRMMapCleanup();
+    return;
+}
+
+
+IMG_VOID
+PVRMMapCleanup(IMG_VOID)
+{
+    PVRSRV_ERROR eError;
+
+    if (!list_empty(&g_sMMapAreaList))
+    {
+       LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+       PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
+
+       PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
+       list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
+       {
+               eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
+               }
+               PVR_ASSERT(eError == PVRSRV_OK);
+
+               LinuxMemAreaDeepFree(psLinuxMemArea);
+       }
+    }
+    PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+    if(g_psMemmapCache)
+    {
+        kmem_cache_destroy(g_psMemmapCache);
+        g_psMemmapCache = NULL;
+    }
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mmap.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mmap.h
new file mode 100644 (file)
index 0000000..73131ec
--- /dev/null
@@ -0,0 +1,102 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include "perproc.h"
+#include "mm.h"
+
+typedef struct KV_OFFSET_STRUCT_TAG
+{
+    
+    IMG_UINT32                 ui32Mapped;
+
+    
+    IMG_UINT32                  ui32MMapOffset;
+    
+    IMG_UINT32                 ui32RealByteSize;
+
+    
+    LinuxMemArea                *psLinuxMemArea;
+    
+    
+    IMG_UINT32                 ui32TID;
+
+    
+    IMG_UINT32                 ui32PID;
+
+    
+    IMG_BOOL                   bOnMMapList;
+
+    
+    IMG_UINT32                 ui32RefCount;
+
+    
+    IMG_UINT32                 ui32UserVAddr;
+
+    
+   struct list_head            sMMapItem;
+
+   
+   struct list_head            sAreaItem;
+}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+
+
+IMG_VOID PVRMMapInit(IMG_VOID);
+
+
+IMG_VOID PVRMMapCleanup(IMG_VOID);
+
+
+PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                            IMG_HANDLE hMHandle,
+                                             IMG_UINT32 *pui32MMapOffset,
+                                             IMG_UINT32 *pui32ByteOffset,
+                                             IMG_UINT32 *pui32RealByteSize,                                                 IMG_UINT32 *pui32UserVAddr);
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                               IMG_HANDLE hMHandle,
+                               IMG_BOOL *pbMUnmap,
+                               IMG_UINT32 *pui32RealByteSize,
+                                IMG_UINT32 *pui32UserVAddr);
+
+int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/module.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/module.c
new file mode 100644 (file)
index 0000000..a7375b2
--- /dev/null
@@ -0,0 +1,743 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(SUPPORT_DRI_DRM)
+       
+       #if defined(LDM_PLATFORM)
+               #define PVR_LDM_PLATFORM_MODULE
+               #define PVR_LDM_MODULE
+       #else
+               #if defined(LDM_PCI)
+                       #define PVR_LDM_PCI_MODULE
+                       #define PVR_LDM_MODULE
+               #endif
+       #endif
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/mutex.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#include <linux/platform_device.h>
+#endif 
+
+#if defined(PVR_LDM_PCI_MODULE)
+#include <linux/pci.h>
+#endif 
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+#include <asm/uaccess.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mm.h"
+#include "mmap.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "private_data.h"
+#include "lock.h"
+#include "linkage.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+#define DRVNAME                "pvrsrvkm"
+#define DEVNAME                "pvrsrvkm"
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+#ifdef DEBUG
+static IMG_INT debug = DBGPRIV_WARNING;
+#include <linux/moduleparam.h>
+module_param(debug, int, 0);
+#endif
+
+
+extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+extern IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+/*EXPORT_SYMBOL(PVRGetDisplayClassJTable); */
+/*EXPORT_SYMBOL(PVRGetBufferClassJTable); */
+
+
+#if defined(PVR_LDM_MODULE)
+static struct class *psPvrClass;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+static IMG_INT AssignedMajorNumber;
+
+static IMG_INT PVRSRVOpen(struct inode* pInode, struct file* pFile);
+static IMG_INT PVRSRVRelease(struct inode* pInode, struct file* pFile);
+
+static struct file_operations pvrsrv_fops = {
+       .owner=THIS_MODULE,
+       .unlocked_ioctl=PVRSRV_BridgeDispatchKM,
+       .open=PVRSRVOpen,
+       .release=PVRSRVRelease,
+       .mmap=PVRMMap,
+};
+#endif
+
+struct mutex gPVRSRVLock;
+
+IMG_UINT32 gui32ReleasePID;
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+static IMG_UINT32 gPVRPowerLevel;
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#define        LDM_DEV struct platform_device
+#define        LDM_DRV struct platform_driver
+#endif 
+
+#if defined(PVR_LDM_PCI_MODULE)
+#define        LDM_DEV struct pci_dev
+#define        LDM_DRV struct pci_driver
+#endif 
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverRemove(LDM_DEV *device);
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *device);
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_VOID PVRSRVDriverRemove(LDM_DEV *device);
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
+#endif
+static IMG_INT PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state);
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *device);
+static IMG_INT PVRSRVDriverResume(LDM_DEV *device);
+
+#if defined(PVR_LDM_PCI_MODULE)
+struct pci_device_id powervr_id_table[] __devinitdata = {
+       { PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID) },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, powervr_id_table);
+#endif
+
+static LDM_DRV powervr_driver = {
+#if defined(PVR_LDM_PLATFORM_MODULE)
+       .driver = {
+               .name           = DRVNAME,
+       },
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+       .name           = DRVNAME,
+       .id_table = powervr_id_table,
+#endif
+       .probe          = PVRSRVDriverProbe,
+#if defined(PVR_LDM_PLATFORM_MODULE)
+       .remove         = PVRSRVDriverRemove,
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+       .remove         = __devexit_p(PVRSRVDriverRemove),
+#endif
+       .suspend        = PVRSRVDriverSuspend,
+       .resume         = PVRSRVDriverResume,
+       .shutdown       = PVRSRVDriverShutdown,
+};
+
+LDM_DEV *gpsPVRLDMDev;
+
+#if defined(MODULE) && defined(PVR_LDM_PLATFORM_MODULE)
+
+static IMG_VOID PVRSRVDeviceRelease(struct device *pDevice)
+{
+       PVR_UNREFERENCED_PARAMETER(pDevice);
+}
+
+static struct platform_device powervr_device = {
+       .name                   = DEVNAME,
+       .id                             = -1,
+       .dev                    = {
+               .release        = PVRSRVDeviceRelease
+       }
+};
+
+#endif 
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_INT __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *id)
+#endif
+{
+       SYS_DATA *psSysData;
+
+       PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
+
+#if 0
+       
+       if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+       {
+               return -EINVAL;
+       }
+#endif 
+       
+       if (SysAcquireData(&psSysData) != PVRSRV_OK)
+       {
+               gpsPVRLDMDev = pDevice;
+
+               if (SysInitialise() != PVRSRV_OK)
+               {
+                       return -ENODEV;
+               }
+       }
+
+       return 0;
+}
+
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_VOID __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+{
+       SYS_DATA *psSysData;
+
+       PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+
+       if (SysAcquireData(&psSysData) == PVRSRV_OK)
+       {
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+               if (gPVRPowerLevel != 0)
+               {
+                       if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+                       {
+                               gPVRPowerLevel = 0;
+                       }
+               }
+#endif
+               SysDeinitialise(psSysData);
+
+               gpsPVRLDMDev = IMG_NULL;
+       }
+
+#if 0
+       if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+       {
+               return -EINVAL;
+       }
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+       return 0;
+#endif
+#if defined (PVR_LDM_PCI_MODULE)
+       return;
+#endif
+}
+
+
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *pDevice)
+{
+       PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+       (IMG_VOID) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+}
+
+#endif 
+
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#else
+static IMG_INT PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+       PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
+       printk(KERN_ALERT  "PVRSRVDriverSuspend(pDevice=%p)", pDevice);
+
+       if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+       {
+               return -EINVAL;
+       }
+#endif
+       return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice)
+#else
+static IMG_INT PVRSRVDriverResume(LDM_DEV *pDevice)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+       PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
+       printk(KERN_ALERT "PVRSRVDriverResume(pDevice=%p)", pDevice);
+
+       if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+       {
+               return -EINVAL;
+       }
+#endif
+       return 0;
+}
+#endif 
+
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+       IMG_CHAR data_buffer[2];
+       IMG_UINT32 PVRPowerLevel;
+
+       if (count != sizeof(data_buffer))
+       {
+               return -EINVAL;
+       }
+       else
+       {
+               if (copy_from_user(data_buffer, buffer, count))
+                       return -EINVAL;
+               if (data_buffer[count - 1] != '\n')
+                       return -EINVAL;
+               PVRPowerLevel = data_buffer[0] - '0';
+               if (PVRPowerLevel != gPVRPowerLevel)
+               {
+                       if (PVRPowerLevel != 0)
+                       {
+                               if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+                               {
+                                       return -EINVAL;
+                               }
+                       }
+                       else
+                       {
+                               if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+                               {
+                                       return -EINVAL;
+                               }
+                       }
+
+                       gPVRPowerLevel = PVRPowerLevel;
+               }
+       }
+       return (count);
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)    
+{
+       seq_printf(sfile, "%lu\n", gPVRPowerLevel);
+}
+
+#else 
+IMG_INT PVRProcGetPowerLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+       if (off == 0) {
+               *start = (IMG_CHAR *)1;
+               return printAppend(page, count, 0, "%lu\n", gPVRPowerLevel);
+       }
+       *eof = 1;
+       return 0;
+}
+#endif 
+
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static IMG_INT PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+       PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+       IMG_HANDLE hBlockAlloc;
+       IMG_INT iRet = -ENOMEM;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32PID;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+       PVR_UNREFERENCED_PARAMETER(dev);
+#else
+       PVR_UNREFERENCED_PARAMETER(pInode);
+#endif
+
+       mutex_lock(&gPVRSRVLock);
+
+       ui32PID = OSGetCurrentProcessIDKM();
+
+       if (PVRSRVProcessConnect(ui32PID) != PVRSRV_OK)
+               goto err_unlock;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       psEnvPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+       if (psEnvPerProc == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: No per-process private data", __FUNCTION__));
+               goto err_unlock;
+       }
+#endif
+
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                               sizeof(PVRSRV_FILE_PRIVATE_DATA),
+                                               (IMG_PVOID *)&psPrivateData,
+                                               &hBlockAlloc,
+                                               "File Private Data");
+
+       if(eError != PVRSRV_OK)
+               goto err_unlock;
+
+#if defined(PVR_SECURE_FD_EXPORT)
+       psPrivateData->hKernelMemInfo = NULL;
+#endif
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       psPrivateData->psDRMFile = pFile;
+
+       list_add_tail(&psPrivateData->sDRMAuthListItem, &psEnvPerProc->sDRMAuthListHead);
+#endif
+       psPrivateData->ui32OpenPID = ui32PID;
+       psPrivateData->hBlockAlloc = hBlockAlloc;
+       PRIVATE_DATA(pFile) = psPrivateData;
+       iRet = 0;
+err_unlock:    
+       mutex_unlock(&gPVRSRVLock);
+       return iRet;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVRelease(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static IMG_INT PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+       PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+
+#if defined(SUPPORT_DRI_DRM)
+       PVR_UNREFERENCED_PARAMETER(dev);
+#else
+       PVR_UNREFERENCED_PARAMETER(pInode);
+#endif
+
+       mutex_lock(&gPVRSRVLock);
+
+       psPrivateData = PRIVATE_DATA(pFile);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       list_del(&psPrivateData->sDRMAuthListItem);
+#endif
+
+       
+       gui32ReleasePID = psPrivateData->ui32OpenPID;
+       PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
+       gui32ReleasePID = 0;
+
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                         sizeof(PVRSRV_FILE_PRIVATE_DATA),
+                         psPrivateData, psPrivateData->hBlockAlloc);
+       PRIVATE_DATA(pFile) = NULL; 
+
+       mutex_unlock(&gPVRSRVLock);
+       return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRCore_Init(IMG_VOID)
+#else
+static IMG_INT __init PVRCore_Init(IMG_VOID)
+#endif
+{
+       IMG_INT error;
+#if !defined(PVR_LDM_MODULE)
+       PVRSRV_ERROR eError;
+#else
+       struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+       
+       PVRDPFInit();
+#endif
+       PVR_TRACE(("PVRCore_Init"));
+
+       mutex_init(&gPVRSRVLock);
+
+#ifdef DEBUG
+       PVRDebugSetLevel(debug);
+#endif
+
+       if (CreateProcEntries ())
+       {
+               error = -ENOMEM;
+               return error;
+       }
+
+       if (PVROSFuncInit() != PVRSRV_OK)
+       {
+               error = -ENOMEM;
+               goto init_failed;
+       }
+
+       PVRLinuxMUtilsInit();
+
+       if (linux_mm_init())
+       {
+               error = -ENOMEM;
+               goto init_failed;
+       }
+
+       LinuxBridgeInit();
+
+       PVRMMapInit();
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+       if ((error = platform_driver_register(&powervr_driver)) != 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error));
+
+               goto init_failed;
+       }
+
+#if defined(MODULE)
+       if ((error = platform_device_register(&powervr_device)) != 0)
+       {
+               platform_driver_unregister(&powervr_driver);
+
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error));
+
+               goto init_failed;
+       }
+#endif
+#endif 
+
+#if defined(PVR_LDM_PCI_MODULE)
+       if ((error = pci_register_driver(&powervr_driver)) != 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
+
+               goto init_failed;
+       }
+#endif 
+
+#else 
+       
+       if ((eError = SysInitialise()) != PVRSRV_OK)
+       {
+               error = -ENODEV;
+#if defined(TCF_REV) && (TCF_REV == 110)
+               if(eError == PVRSRV_ERROR_NOT_SUPPORTED)
+               {
+                       printk("\nAtlas wrapper (FPGA image) version mismatch");
+                       error = -ENODEV;
+               }
+#endif
+               goto init_failed;
+       }
+#endif 
+
+#if !defined(SUPPORT_DRI_DRM)
+       AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
+
+       if (AssignedMajorNumber <= 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number"));
+
+               error = -EBUSY;
+               goto sys_deinit;
+       }
+
+       PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
+#endif 
+
+#if defined(PVR_LDM_MODULE)
+       
+       psPvrClass = class_create(THIS_MODULE, "pvr");
+
+       if (IS_ERR(psPvrClass))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass)));
+               error = -EBUSY;
+               goto unregister_device;
+       }
+
+       psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0), NULL, DEVNAME);
+       if (IS_ERR(psDev))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev)));
+               error = -EBUSY;
+               goto destroy_class;
+       }
+#endif 
+
+       return 0;
+
+#if defined(PVR_LDM_MODULE)
+destroy_class:
+       class_destroy(psPvrClass);
+unregister_device:
+       unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+#endif
+#if !defined(SUPPORT_DRI_DRM)
+sys_deinit:
+#endif
+#if defined(PVR_LDM_MODULE)
+#if defined(PVR_LDM_PCI_MODULE)
+       pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined (MODULE)
+       platform_device_unregister(&powervr_device);
+#endif
+       platform_driver_unregister(&powervr_driver);
+#endif
+
+#else  
+       
+       {
+               SYS_DATA *psSysData;
+
+               SysAcquireData(&psSysData);
+               if (psSysData != IMG_NULL)
+               {
+                       SysDeinitialise(psSysData);
+               }
+       }
+#endif 
+init_failed:
+       PVRMMapCleanup();
+       linux_mm_cleanup();
+       LinuxBridgeDeInit();
+       PVROSFuncDeInit();
+       RemoveProcEntries();
+
+       return error;
+
+} 
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_VOID PVRCore_Cleanup(IMG_VOID)
+#else
+static IMG_VOID __exit PVRCore_Cleanup(IMG_VOID)
+#endif
+{
+       SYS_DATA *psSysData;
+
+       PVR_TRACE(("PVRCore_Cleanup"));
+
+       SysAcquireData(&psSysData);
+
+#if defined(PVR_LDM_MODULE)
+       device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+       class_destroy(psPvrClass);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+       unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+#endif 
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PCI_MODULE)
+       pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined (MODULE)
+       platform_device_unregister(&powervr_device);
+#endif
+       platform_driver_unregister(&powervr_driver);
+#endif
+
+#else 
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+       if (gPVRPowerLevel != 0)
+       {
+               if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+               {
+                       gPVRPowerLevel = 0;
+               }
+       }
+#endif
+       
+       SysDeinitialise(psSysData);
+#endif 
+
+       PVRMMapCleanup();
+
+       linux_mm_cleanup();
+
+       LinuxBridgeDeInit();
+
+       PVROSFuncDeInit();
+
+       RemoveProcEntries();
+
+       PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+#if !defined(SUPPORT_DRI_DRM)
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mutils.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mutils.c
new file mode 100644 (file)
index 0000000..d9ad5ff
--- /dev/null
@@ -0,0 +1,130 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mutils.h"
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+#define        PAT_LINUX_X86_WC        1
+
+#define        PAT_X86_ENTRY_BITS      8
+
+#define        PAT_X86_BIT_PWT         1U
+#define        PAT_X86_BIT_PCD         2U
+#define        PAT_X86_BIT_PAT         4U
+#define        PAT_X86_BIT_MASK        (PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT)
+
+static IMG_BOOL g_write_combining_available = IMG_FALSE;
+
+#define        PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0)
+
+static inline IMG_UINT
+pvr_pat_index(pgprotval_t prot_val)
+{
+       IMG_UINT ret = 0;
+       pgprotval_t val = prot_val & _PAGE_CACHE_MASK;
+
+       ret |= PROT_TO_PAT_INDEX(val, PAT);
+       ret |= PROT_TO_PAT_INDEX(val, PCD);
+       ret |= PROT_TO_PAT_INDEX(val, PWT);
+
+       return ret;
+}
+
+static inline IMG_UINT
+pvr_pat_entry(u64 pat, IMG_UINT index)
+{
+       return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK;
+}
+
+static IMG_VOID
+PVRLinuxX86PATProbe(IMG_VOID)
+{
+       
+       if (cpu_has_pat)         
+       {
+               u64 pat;
+               IMG_UINT pat_index;
+               IMG_UINT pat_entry;
+
+               PVR_TRACE(("%s: PAT available", __FUNCTION__));
+               
+               rdmsrl(MSR_IA32_CR_PAT, pat);
+               PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
+               PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
+
+               pat_index = pvr_pat_index(_PAGE_CACHE_WC);
+               PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index));
+
+               pat_entry = pvr_pat_entry(pat, pat_index);
+               PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC));
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+               g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC);
+#endif
+       }
+#if defined(DEBUG)
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+       if (g_write_combining_available)
+       {
+               PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__));
+       }
+       else
+       {
+               PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
+       }
+#else  
+       PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
+#endif 
+#endif 
+}
+
+pgprot_t
+pvr_pgprot_writecombine(pgprot_t prot)
+{
+    
+     
+    return (g_write_combining_available) ?
+               __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
+}
+#endif 
+
+IMG_VOID
+PVRLinuxMUtilsInit(IMG_VOID)
+{
+#if defined(SUPPORT_LINUX_X86_PAT)
+       PVRLinuxX86PATProbe();
+#endif
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mutils.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/mutils.h
new file mode 100644 (file)
index 0000000..0360bee
--- /dev/null
@@ -0,0 +1,85 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#include <linux/version.h>
+
+#if !(defined(__i386__))
+#if defined(SUPPORT_LINUX_X86_PAT)
+#undef SUPPORT_LINUX_X86_PAT
+#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+       pgprot_t pvr_pgprot_writecombine(pgprot_t prot);
+       #define PGPROT_WC(pv)   pvr_pgprot_writecombine(pv)
+#else
+       #if defined(__arm__) || defined(__sh__)
+               #define PGPROT_WC(pv)   pgprot_writecombine(pv)
+       #else
+               #if defined(__i386__)
+                       #define PGPROT_WC(pv)   pgprot_noncached(pv)
+               #else
+                       #define PGPROT_WC(pv)   pgprot_noncached(pv)
+                       #error  Unsupported architecture!
+               #endif
+       #endif
+#endif
+
+#define        PGPROT_UC(pv)   pgprot_noncached(pv)
+
+#if defined(__i386__)
+       #define IOREMAP(pa, bytes)      ioremap_cache(pa, bytes)
+#else  
+       #if defined(__arm__)
+               #define IOREMAP(pa, bytes)      ioremap_cached(pa, bytes)
+       #else
+               #define IOREMAP(pa, bytes)      ioremap(pa, bytes)
+       #endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+       #if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+               #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+       #else
+               #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+       #endif
+#else
+       #if defined(__arm__)
+               #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+       #else
+               #define IOREMAP_WC(pa, bytes)   ioremap_nocache(pa, bytes)
+       #endif
+#endif
+
+#define        IOREMAP_UC(pa, bytes)   ioremap_nocache(pa, bytes)
+
+IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/osfunc.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/osfunc.c
new file mode 100644 (file)
index 0000000..640d9d3
--- /dev/null
@@ -0,0 +1,2446 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+#include <asm/cacheflush.h>
+#endif
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h> 
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \
+       defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \
+       defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \
+       defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "event.h"
+#include "linkage.h"
+
+#define EVENT_OBJECT_TIMEOUT_MS                (100)
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS) || \
+       defined(SUPPORT_CACHEFLUSH_ON_ALLOC)
+
+#if defined(__i386__)
+static void per_cpu_cache_flush(void *arg)
+{
+    PVR_UNREFERENCED_PARAMETER(arg);
+    wbinvd();
+}
+#endif 
+
+#if !defined(SUPPORT_CPU_CACHED_BUFFERS)
+static
+#endif
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+#if defined(__arm__)
+    flush_cache_all();
+#elif defined(__i386__)
+    
+    on_each_cpu(per_cpu_cache_flush, NULL, 1);
+#else
+#error "Implement full CPU cache flush for this CPU!"
+#endif
+}
+
+#endif 
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+
+IMG_VOID OSFlushCPUCacheRangeKM(IMG_VOID *pvRangeAddrStart,
+                                                               IMG_VOID *pvRangeAddrEnd)
+{
+       PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+       PVR_UNREFERENCED_PARAMETER(pvRangeAddrEnd);
+
+       
+       OSFlushCPUCacheKM();
+}
+
+#endif 
+
+#define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0)
+#define HOST_ALLOC_MEM_USING_VMALLOC ((IMG_HANDLE)1)
+
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
+{
+    PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+    *ppvCpuVAddr = kmalloc(ui32Size, GFP_KERNEL);
+
+    if(*ppvCpuVAddr)
+    {
+    if (phBlockAlloc)
+    {
+        
+        *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
+    }
+    }
+    else
+    {
+    if (!phBlockAlloc)
+    {
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+    
+    *ppvCpuVAddr = vmalloc_wrapper(ui32Size, PVRSRV_HAP_CACHED);
+    if (!*ppvCpuVAddr)
+    {
+         return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+    
+    *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
+    }
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+{      
+    PVR_UNREFERENCED_PARAMETER(ui32Flags);
+    PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+    if (hBlockAlloc == HOST_ALLOC_MEM_USING_VMALLOC)
+    {
+           vfree(pvCpuVAddr);
+    }
+    else
+    {
+        kfree(pvCpuVAddr);
+    }
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
+                IMG_UINT32 ui32Size,
+                IMG_UINT32 ui32PageSize,
+                IMG_VOID **ppvCpuVAddr,
+                IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+#if 0
+    
+    if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
+    {
+        ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+        ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS;
+    }
+#endif
+
+    switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+            psLinuxMemArea = vmalloc_linux_mem_area(ui32Size, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+            
+            
+            psLinuxMemArea = alloc_pages_linux_mem_area(ui32Size, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            
+#if defined(VIVT_CACHE) || defined(__sh__)
+            
+            ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+            psLinuxMemArea = vmalloc_linux_mem_area(ui32Size, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n", ui32AllocFlags));
+            *ppvCpuVAddr = NULL;
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+#if defined(SUPPORT_CACHEFLUSH_ON_ALLOC)
+    
+    if(ui32AllocFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
+    {
+        OSFlushCPUCacheKM();
+    }
+#endif 
+
+    *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+    *phOSMemHandle = psLinuxMemArea;
+    
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
+{   
+    LinuxMemArea *psLinuxMemArea;
+    PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+    
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+            if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+            {
+                PVR_DPF((PVR_DBG_ERROR,
+                         "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%ld, "
+                                        "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
+                         ui32AllocFlags, ui32Bytes, pvCpuVAddr, hOSMemHandle));
+                return PVRSRV_ERROR_GENERIC;
+            }
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"%s: invalid flags 0x%x\n",
+                    __FUNCTION__, ui32AllocFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+                  IMG_UINT32 ui32ByteOffset,
+                  IMG_UINT32 ui32Bytes,
+                  IMG_UINT32 ui32Flags,
+                  IMG_HANDLE *phOSMemHandleRet)
+{
+    LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+
+    psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    
+    psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
+    if(!psLinuxMemArea)
+    {
+        *phOSMemHandleRet = NULL;
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+    *phOSMemHandleRet = psLinuxMemArea;
+
+    
+    if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+        return PVRSRV_OK;
+    }
+
+    eError = PVRMMapRegisterArea(psLinuxMemArea);
+    if(eError != PVRSRV_OK)
+     {
+        goto failed_register_area;
+    }
+
+    return PVRSRV_OK;
+
+failed_register_area:
+    *phOSMemHandleRet = NULL;
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+    return eError;
+}
+
+PVRSRV_ERROR
+OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+    
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+    
+    if((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0)
+    {
+        eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+        if(eError != PVRSRV_OK)
+        {
+            return eError;
+        }
+    }
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+IMG_CPU_PHYADDR
+OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset)
+{
+       IMG_CPU_PHYADDR cpu_addr;
+       BUG_ON(!hOSMemHandle);
+
+       memset(&cpu_addr, 0, sizeof(cpu_addr));
+
+       cpu_addr.uiAddr = LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+
+       return cpu_addr;
+}
+
+
+
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+    IMG_UINT8 *Src,*Dst;
+    IMG_INT i;
+
+    Src=(IMG_UINT8 *)pvSrc;
+    Dst=(IMG_UINT8 *)pvDst;
+    for(i=0;i<ui32Size;i++)
+    {
+        Dst[i]=Src[i];
+    }
+#else
+    memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMSET)
+    IMG_UINT8 *Buff;
+    IMG_INT i;
+
+    Buff=(IMG_UINT8 *)pvDest;
+    for(i=0;i<ui32Size;i++)
+    {
+        Buff[i]=ui8Value;
+    }
+#else
+    memset(pvDest, (IMG_INT) ui8Value, (size_t) ui32Size);
+#endif
+}
+
+
+IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
+{
+    return (strcpy(pszDest, pszSrc));
+}
+
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
+{
+    va_list argList;
+    IMG_INT32 iCount;
+
+    va_start(argList, pszFormat);
+    iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList);
+    va_end(argList);
+
+    return iCount;
+}
+
+IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+    if(*pui32Access)
+    {
+        if(psResource->ui32ID == ui32ID)
+        {
+            psResource->ui32ID = 0;
+            *pui32Access = 0;
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked for this process.")); 
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked"));
+    }
+}
+
+
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
+{
+    psResource->ui32ID = 0;
+    psResource->ui32Lock = 0;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
+{
+    OSBreakResourceLock (psResource, psResource->ui32ID);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
+{
+    ENV_DATA           *psEnvData;
+    
+    
+    if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
+        "Environment Data") != PVRSRV_OK)
+    {
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, 
+                    &psEnvData->pvBridgeData, IMG_NULL,
+                    "Bridge Data") != PVRSRV_OK)
+    {
+        OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
+               
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+
+    
+    psEnvData->bMISRInstalled = IMG_FALSE;
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+    
+    *ppvEnvSpecificData = psEnvData;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
+{
+    ENV_DATA           *psEnvData = (ENV_DATA*)pvEnvSpecificData;
+
+    PVR_ASSERT(!psEnvData->bMISRInstalled);
+    PVR_ASSERT(!psEnvData->bLISRInstalled);
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, psEnvData->pvBridgeData, IMG_NULL);
+    psEnvData->pvBridgeData = IMG_NULL;
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
+       
+
+    return PVRSRV_OK;
+}
+
+
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
+{
+    schedule();
+}
+
+
+IMG_UINT32 OSClockus(IMG_VOID)
+{
+    IMG_UINT32 time, j = jiffies;
+
+    time = j * (1000000 / HZ);
+
+    return time;
+}
+
+
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
+{
+    udelay(ui32Timeus);
+}
+
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
+{
+    if (in_interrupt())
+    {
+        return KERNEL_ID;
+    }
+
+    return (IMG_UINT32)task_tgid_nr(current);
+}
+
+
+IMG_UINT32 OSGetPageSize(IMG_VOID)
+{
+#if defined(__sh__)
+    IMG_UINT32 ui32ReturnValue = PAGE_SIZE;
+
+    return (ui32ReturnValue);
+#else
+    return PAGE_SIZE;
+#endif
+}
+
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
+        )
+{
+    PVRSRV_DEVICE_NODE *psDeviceNode;
+    IMG_BOOL bStatus = IMG_FALSE;
+
+    PVR_UNREFERENCED_PARAMETER(irq);
+
+    psDeviceNode = (PVRSRV_DEVICE_NODE*)dev_id;
+    if(!psDeviceNode)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n"));
+        goto out;
+    }
+
+    bStatus = PVRSRVDeviceLISR(psDeviceNode);
+
+    if (bStatus)
+    {
+               OSScheduleMISR((IMG_VOID *)psDeviceNode->psSysData);
+    }
+
+out:
+    return bStatus ? IRQ_HANDLED : IRQ_NONE;
+}
+
+
+
+static irqreturn_t SystemISRWrapper(int irq, void *dev_id)
+{
+    SYS_DATA *psSysData;
+    IMG_BOOL bStatus = IMG_FALSE;
+
+    PVR_UNREFERENCED_PARAMETER(irq);
+
+    psSysData = (SYS_DATA *)dev_id;
+    if(!psSysData)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "SystemISRWrapper: invalid params\n"));
+        goto out;
+    }
+
+    bStatus = PVRSRVSystemLISR(psSysData);
+
+    if (bStatus)
+    {
+        OSScheduleMISR((IMG_VOID *)psSysData);
+    }
+
+out:
+    return bStatus ? IRQ_HANDLED : IRQ_NONE;
+}
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+                                    IMG_UINT32 ui32Irq,
+                                    IMG_CHAR *pszISRName,
+                                    IMG_VOID *pvDeviceNode)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %x", pszISRName, ui32Irq, pvDeviceNode));
+
+    if(request_irq(ui32Irq, DeviceISRWrapper, IRQF_SHARED, pszISRName, pvDeviceNode))
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", ui32Irq));
+
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    psEnvData->ui32IRQ = ui32Irq;
+    psEnvData->pvISRCookie = pvDeviceNode;
+    psEnvData->bLISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;  
+}
+
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallDeviceLISR: No LISR has been installed"));
+        return PVRSRV_ERROR_GENERIC;
+    }
+        
+    PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %x", psEnvData->ui32IRQ,  psEnvData->pvISRCookie));
+
+    free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    PVR_TRACE(("Installing system LISR on IRQ %d with cookie %x", ui32Irq, pvSysData));
+
+    if(request_irq(ui32Irq, SystemISRWrapper, IRQF_SHARED, "PowerVR", pvSysData))
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Couldn't install system LISR on IRQ %d", ui32Irq));
+
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    psEnvData->ui32IRQ = ui32Irq;
+    psEnvData->pvISRCookie = pvSysData;
+    psEnvData->bLISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;  
+}
+
+
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallSystemLISR: No LISR has been installed"));
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+    free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+    return PVRSRV_OK;
+}
+
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+static void MISRWrapper(struct work_struct *data)
+{
+       ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+       SYS_DATA *psSysData  = (SYS_DATA *)psEnvData->pvMISRData;
+
+       PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+       if (psEnvData->bMISRInstalled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+       psEnvData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
+
+       if (psEnvData->psWorkQueue == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       INIT_WORK(&psEnvData->sMISRWork, MISRWrapper);
+
+       psEnvData->pvMISRData = pvSysData;
+       psEnvData->bMISRInstalled = IMG_TRUE;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+       if (!psEnvData->bMISRInstalled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       PVR_TRACE(("Uninstalling MISR"));
+
+       destroy_workqueue(psEnvData->psWorkQueue);
+
+       psEnvData->bMISRInstalled = IMG_FALSE;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+       if (psEnvData->bMISRInstalled)
+       {
+               queue_work(psEnvData->psWorkQueue, &psEnvData->sMISRWork);
+       }
+
+       return PVRSRV_OK;       
+}
+#else  
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+static void MISRWrapper(struct work_struct *data)
+{
+       ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+       SYS_DATA *psSysData  = (SYS_DATA *)psEnvData->pvMISRData;
+
+       PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+       if (psEnvData->bMISRInstalled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       PVR_TRACE(("Installing MISR with cookie %x", pvSysData));
+
+       INIT_WORK(&psEnvData->sMISRWork, MISRWrapper);
+
+       psEnvData->pvMISRData = pvSysData;
+       psEnvData->bMISRInstalled = IMG_TRUE;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+       if (!psEnvData->bMISRInstalled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       PVR_TRACE(("Uninstalling MISR"));
+
+       flush_scheduled_work();
+
+       psEnvData->bMISRInstalled = IMG_FALSE;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+       if (psEnvData->bMISRInstalled)
+       {
+               schedule_work(&psEnvData->sMISRWork);
+       }
+
+       return PVRSRV_OK;       
+}
+
+#else  
+
+
+static void MISRWrapper(unsigned long data)
+{
+    SYS_DATA *psSysData;
+
+    psSysData = (SYS_DATA *)data;
+    
+    PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bMISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    PVR_TRACE(("Installing MISR with cookie %x", pvSysData));
+
+    tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, (unsigned long)pvSysData);
+
+    psEnvData->bMISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bMISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    PVR_TRACE(("Uninstalling MISR"));
+
+    tasklet_kill(&psEnvData->sMISRTasklet);
+
+    psEnvData->bMISRInstalled = IMG_FALSE;
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bMISRInstalled)
+    {
+        tasklet_schedule(&psEnvData->sMISRTasklet);
+    }
+
+    return PVRSRV_OK;  
+}
+
+#endif 
+#endif 
+
+
+IMG_VOID OSPanic(IMG_VOID)
+{
+       BUG();
+}
+
+#define        OS_TAS(p)       xchg((p), 1)
+PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE  *psResource,
+                                IMG_UINT32                     ui32ID)
+
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(!OS_TAS(&psResource->ui32Lock))
+        psResource->ui32ID = ui32ID;
+    else
+        eError = PVRSRV_ERROR_GENERIC;
+
+    return eError;
+}
+
+
+PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(*pui32Access)
+    {
+        if(psResource->ui32ID == ui32ID)
+        {
+            psResource->ui32ID = 0;
+            *pui32Access = 0;
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked with expected value.", psResource)); 
+            PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID));
+            eError = PVRSRV_ERROR_GENERIC;
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked", psResource));
+        eError = PVRSRV_ERROR_GENERIC;
+    }
+    
+    return eError;
+}
+
+
+IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+    return     (*(volatile IMG_UINT32 *)pui32Access == 1) && (psResource->ui32ID == ui32ID)
+            ?  IMG_TRUE
+            :  IMG_FALSE;
+}
+
+
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_VOID *pvLinAddr)
+{
+    IMG_CPU_PHYADDR CpuPAddr;
+
+    CpuPAddr.uiAddr = (IMG_UINTPTR_T)VMallocToPhys(pvLinAddr);
+
+    return CpuPAddr;
+}
+
+
+IMG_VOID *
+OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+               IMG_UINT32 ui32Bytes,
+               IMG_UINT32 ui32MappingFlags,
+               IMG_HANDLE *phOSMemHandle)
+{
+    if(phOSMemHandle)
+    {
+        *phOSMemHandle = (IMG_HANDLE)0;
+    }
+
+    if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+        IMG_VOID *pvIORemapCookie;
+        pvIORemapCookie = ioremap_wrapper(BasePAddr.uiAddr, ui32Bytes, ui32MappingFlags);
+        if(pvIORemapCookie == IMG_NULL)
+        {
+            return NULL;
+        }
+        return pvIORemapCookie;
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+                 "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+                 " (Use OSReservePhys otherwise)"));
+        return NULL;
+    }
+}
+
+IMG_BOOL
+OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hPageAlloc)
+{
+    PVR_TRACE(("%s: unmapping %d bytes from 0x%08x", __FUNCTION__, ui32Bytes, pvLinAddr));
+
+    PVR_UNREFERENCED_PARAMETER(hPageAlloc);    
+    PVR_UNREFERENCED_PARAMETER(ui32Bytes);     
+
+    if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+        iounmap(pvLinAddr);
+        return IMG_TRUE;
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+                     "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+                     " (Use OSUnReservePhys otherwise)"));
+        return IMG_FALSE;
+    }
+}
+
+static PVRSRV_ERROR
+RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
+          IMG_VOID *pvCPUVAddr,
+              IMG_UINT32 ui32Bytes,
+          IMG_BOOL bPhysContig,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+        
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_GENERIC;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_GENERIC;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            
+#if defined(VIVT_CACHE) || defined(__sh__)
+            
+            ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_GENERIC;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"OSRegisterMem : invalid flags 0x%x\n", ui32MappingFlags));
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_GENERIC;
+    }
+    
+    *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+              IMG_VOID *pvCPUVAddr,
+              IMG_UINT32 ui32Bytes,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_HANDLE *phOSMemHandle)
+{
+    IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
+
+    return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
+{
+    return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR
+OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
+                IMG_UINT32 ui32Bytes,
+                IMG_UINT32 ui32MappingFlags,
+                IMG_HANDLE hOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+    PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+            {
+                 PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+                          __FUNCTION__, pvCpuVAddr, ui32Bytes,
+                          ui32MappingFlags, hOSMemHandle));
+                return PVRSRV_ERROR_GENERIC;
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSUnRegisterMem : invalid flags 0x%x", ui32MappingFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+    return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+}
+
+PVRSRV_ERROR
+OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
+              IMG_UINT32 ui32Bytes,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_VOID **ppvCpuVAddr,
+              IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+#if 0
+    
+    if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
+    {
+        ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+        ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS;
+    }
+#endif
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+            
+            psLinuxMemArea = ioremap_linux_mem_area(BasePAddr.uiAddr, ui32Bytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_GENERIC;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+            
+            psLinuxMemArea = NewIOLinuxMemArea(BasePAddr.uiAddr, ui32Bytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_GENERIC;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            
+#if defined(VIVT_CACHE) || defined(__sh__)
+            
+            ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+            psLinuxMemArea = ioremap_linux_mem_area(BasePAddr.uiAddr, ui32Bytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_GENERIC;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"OSMapPhysToLin : invalid flags 0x%x\n", ui32MappingFlags));
+            *ppvCpuVAddr = NULL;
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_GENERIC;
+    }
+
+    *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+    *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+OSUnReservePhys(IMG_VOID *pvCpuVAddr,
+                IMG_UINT32 ui32Bytes,
+                IMG_UINT32 ui32MappingFlags,
+                IMG_HANDLE hOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+   PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+            {
+                 PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+                          __FUNCTION__, pvCpuVAddr, ui32Bytes,
+                          ui32MappingFlags, hOSMemHandle));
+                return PVRSRV_ERROR_GENERIC;
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSUnMapPhysToLin : invalid flags 0x%x", ui32MappingFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+    
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+    PVR_UNREFERENCED_PARAMETER(ui32Size);
+    PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+    PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
+
+    return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+    IMG_VOID *pvKernLinAddr;
+
+    pvKernLinAddr = kmalloc(ui32Size, GFP_KERNEL);
+
+    if (!pvKernLinAddr)
+    {
+    return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+    *pvLinAddr = pvKernLinAddr;
+
+    psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
+
+    return PVRSRV_OK;
+#endif 
+}
+
+
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+    PVR_UNREFERENCED_PARAMETER(ui32Size);
+    PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+    PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
+#else
+    PVR_UNREFERENCED_PARAMETER(ui32Size);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+    kfree(pvLinAddr);
+#endif
+    return PVRSRV_OK;
+}
+
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+    return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+    return *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+    writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+    *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+#endif
+}
+
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
+{
+    int err;
+    IMG_UINT32 i;
+    PVR_PCI_DEV *psPVRPCI;
+
+    PVR_TRACE(("OSPCISetDev"));
+
+    if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID **)&psPVRPCI, IMG_NULL,
+        "PCI Device") != PVRSRV_OK)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't allocate PVR PCI structure"));
+        return IMG_NULL;
+    }
+
+    psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
+    psPVRPCI->ePCIFlags = eFlags;
+
+    err = pci_enable_device(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't enable device (%d)", err));
+        return IMG_NULL;
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)    
+    {
+        pci_set_master(psPVRPCI->psPCIDev);
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)           
+    {
+#if defined(CONFIG_PCI_MSI)
+       if (psPVRPCI->psPCIDev->device == PSB_SYS_SGX_DEV_DEVICE_ID_1 ||
+           psPVRPCI->psPCIDev->device == PSB_SYS_SGX_DEV_DEVICE_ID_2) // Disable MSI for Menlow
+               psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;  
+       else if(!psPVRPCI->psPCIDev->msi_enabled) 
+               /* MSIs enabled at probe() time */
+               psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;  
+#else
+        PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
+#endif
+    }
+
+    
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+    }
+
+    return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
+}
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags)
+{
+    struct pci_dev *psPCIDev;
+
+    psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
+    if (psPCIDev == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIAcquireDev: Couldn't acquire device"));
+        return IMG_NULL;
+    }
+
+    return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
+}
+
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+    *pui32IRQ = psPVRPCI->psPCIDev->irq;
+
+    return PVRSRV_OK;
+}
+
+enum HOST_PCI_ADDR_RANGE_FUNC
+{
+    HOST_PCI_ADDR_RANGE_FUNC_LEN,
+    HOST_PCI_ADDR_RANGE_FUNC_START,
+    HOST_PCI_ADDR_RANGE_FUNC_END,
+    HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
+    HOST_PCI_ADDR_RANGE_FUNC_RELEASE
+};
+
+static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
+                                     PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+                                     IMG_UINT32 ui32Index)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+    if (ui32Index >= DEVICE_COUNT_RESOURCE)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Index out of range"));
+        return 0;
+
+    }
+
+    switch (eFunc)
+    {
+        case HOST_PCI_ADDR_RANGE_FUNC_LEN:
+            return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_START:
+            return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_END:
+            return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
+        {
+            int err;
+
+            err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, "PowerVR");
+            if (err != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err));
+                return 0;
+            }
+            psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
+            return 1;
+        }
+        case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
+            if (psPVRPCI->abPCIResourceInUse[ui32Index])
+            {
+                pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index);
+                psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
+            }
+            return 1;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Unknown function"));
+            break;
+    }
+
+    return 0;
+}
+
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index); 
+}
+
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index); 
+}
+
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index); 
+}
+
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+                                   IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_GENERIC : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_GENERIC : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int i;
+
+    PVR_TRACE(("OSPCIReleaseDev"));
+
+    
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i));
+            pci_release_region(psPVRPCI->psPCIDev, i);
+            psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+        }
+    }
+
+#if defined(CONFIG_PCI_MSI)
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)           
+    {
+        pci_disable_msi(psPVRPCI->psPCIDev);
+    }
+#endif
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)    
+    {
+        pci_clear_master(psPVRPCI->psPCIDev);
+    }
+    pci_disable_device(psPVRPCI->psPCIDev);
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
+       
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int i;
+    int err;
+
+    PVR_TRACE(("OSPCISuspendDev"));
+
+    
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            pci_release_region(psPVRPCI->psPCIDev, i);
+        }
+    }
+
+    err = pci_save_state(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_save_state_failed (%d)", err));
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    pci_disable_device(psPVRPCI->psPCIDev);
+
+    err = pci_set_power_state(psPVRPCI->psPCIDev, PCI_D3hot);//pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND));
+    switch(err)
+    {
+        case 0:
+            break;
+        case -EIO:
+            PVR_DPF((PVR_DBG_WARNING, "OSPCISuspendDev: device doesn't support PCI PM"));
+            break;
+        case -EINVAL:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: can't enter requested power state"));
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_set_power_state failed (%d)", err));
+            break;
+    }
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int err;
+    int i;
+
+    PVR_TRACE(("OSPCIResumeDev"));
+
+    err = pci_set_power_state(psPVRPCI->psPCIDev, PCI_D0);//pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
+    switch(err)
+    {
+        case 0:
+            break;
+        case -EIO:
+            PVR_DPF((PVR_DBG_WARNING, "OSPCIResumeDev: device doesn't support PCI PM"));
+            break;
+        case -EINVAL:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: can't enter requested power state"));
+            return PVRSRV_ERROR_GENERIC;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_set_power_state failed (%d)", err));
+            return PVRSRV_ERROR_GENERIC;
+    }
+
+    pci_restore_state(psPVRPCI->psPCIDev);
+
+    err = pci_enable_device(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: Couldn't enable device (%d)", err));
+        return PVRSRV_ERROR_GENERIC;
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)    
+        pci_set_master(psPVRPCI->psPCIDev);
+
+    
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            err = pci_request_region(psPVRPCI->psPCIDev, i, "PowerVR");
+            if (err != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)", i, err));
+            }
+        }
+
+    }
+
+    return PVRSRV_OK;
+}
+
+#define        OS_MAX_TIMERS   8
+
+typedef struct TIMER_CALLBACK_DATA_TAG
+{
+    IMG_BOOL           bInUse;
+    PFN_TIMER_FUNC             pfnTimerFunc;
+    IMG_VOID           *pvData;        
+    struct timer_list  sTimer;
+    IMG_UINT32                 ui32Delay;
+    IMG_BOOL                   bActive;
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+       struct work_struct      sWork;
+#endif
+}TIMER_CALLBACK_DATA;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static struct workqueue_struct *psTimerWorkQueue;
+#endif
+
+static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+DEFINE_MUTEX(sTimerStructLock);
+#else
+static DEFINE_SPINLOCK(sTimerStructLock);
+#endif
+
+static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
+{    
+    if (!psTimerCBData->bActive)
+        return;
+
+    
+    psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+    
+    
+    mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork);
+
+    OSTimerCallbackBody(psTimerCBData);
+}
+#endif
+
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
+{
+    TIMER_CALLBACK_DATA        *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
+    
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    int res;
+
+    res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork);
+    if (res == 0)
+    {
+        PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued"));             
+    }
+#else
+    OSTimerCallbackBody(psTimerCBData);
+#endif
+}
+
+
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
+{
+    TIMER_CALLBACK_DATA        *psTimerCBData;
+    IMG_UINT32         ui32i;
+#if !defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    unsigned long              ulLockFlags;
+#endif
+
+    
+    if(!pfnTimerFunc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));               
+        return IMG_NULL;               
+    }
+    
+    
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    mutex_lock(&sTimerStructLock);
+#else
+    spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+#endif
+    for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+    {
+        psTimerCBData = &sTimers[ui32i];
+        if (!psTimerCBData->bInUse)
+        {
+            psTimerCBData->bInUse = IMG_TRUE;
+            break;
+        }
+    }
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    mutex_unlock(&sTimerStructLock);
+#else
+    spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+#endif
+    if (ui32i >= OS_MAX_TIMERS)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));         
+        return IMG_NULL;       
+    }
+
+    psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+    psTimerCBData->pvData = pvData;
+    psTimerCBData->bActive = IMG_FALSE;
+    
+    
+
+
+    psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+                                ?      1
+                                :      ((HZ * ui32MsTimeout) / 1000);
+    
+    init_timer(&psTimerCBData->sTimer);
+    
+    
+    psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
+    psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
+    psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+    
+    return (IMG_HANDLE)(ui32i + 1);
+}
+
+
+static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
+{
+    IMG_UINT32 ui32i = ((IMG_UINT32)hTimer) - 1;
+
+    PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+
+    return &sTimers[ui32i];
+}
+
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(!psTimerCBData->bActive);
+
+    
+    psTimerCBData->bInUse = IMG_FALSE;
+    
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(!psTimerCBData->bActive);
+
+    
+    psTimerCBData->bActive = IMG_TRUE;
+
+    
+    psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+    
+    add_timer(&psTimerCBData->sTimer);
+    
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(psTimerCBData->bActive);
+
+    
+    psTimerCBData->bActive = IMG_FALSE;
+       smp_mb();
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+       flush_workqueue(psTimerWorkQueue);
+#endif
+
+    
+    del_timer_sync(&psTimerCBData->sTimer);    
+    
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    
+       flush_workqueue(psTimerWorkQueue);
+#endif
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *psEventObject)
+{
+
+    PVRSRV_ERROR eError = PVRSRV_OK;
+    
+    if(psEventObject)
+    {
+        if(pszName)
+        {
+            
+            strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
+        }
+        else
+        {
+               
+            static IMG_UINT16 ui16NameIndex = 0;                       
+            snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
+        }
+        
+        if(LinuxEventObjectListCreate(&psEventObject->hOSEventKM) != PVRSRV_OK)
+        {
+             eError = PVRSRV_ERROR_OUT_OF_MEMORY;      
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_GENERIC; 
+    }
+    
+    return eError;
+
+}
+
+
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(psEventObject)
+    {
+        if(psEventObject->hOSEventKM)
+        {
+            LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: hOSEventKM is not a valid pointer"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+}
+
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError;
+    
+    if(hOSEventKM)
+    {
+        eError = LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWait: hOSEventKM is not a valid handle"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+}
+
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+                                            IMG_HANDLE *phOSEvent)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+    
+    if(psEventObject)
+    {
+        if(LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) != PVRSRV_OK)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+}
+
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+                                            IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(psEventObject)
+    {
+        if(LinuxEventObjectDelete(psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+    
+}
+
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError;
+    
+    if(hOSEventKM)
+    {
+        eError = LinuxEventObjectSignal(hOSEventKM);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignal: hOSEventKM is not a valid handle"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+}
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
+{
+    return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, 
+                          IMG_VOID *pvDest, 
+                          IMG_VOID *pvSrc, 
+                          IMG_UINT32 ui32Bytes)
+{
+    PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+    if(copy_to_user(pvDest, pvSrc, ui32Bytes)==0)
+        return PVRSRV_OK;
+    else
+        return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess, 
+                             IMG_VOID *pvDest, 
+                             IMG_VOID *pvSrc, 
+                             IMG_UINT32 ui32Bytes)
+{
+    PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+    if(copy_from_user(pvDest, pvSrc, ui32Bytes)==0)
+        return PVRSRV_OK;
+    else
+        return PVRSRV_ERROR_GENERIC;
+}
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
+{
+    IMG_INT linuxType;
+
+    if (eVerification == PVR_VERIFY_READ)
+    {
+        linuxType = VERIFY_READ;
+    }
+    else
+    {
+        PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+        linuxType = VERIFY_WRITE;
+    }
+
+    return access_ok(linuxType, pvUserPtr, ui32Bytes);
+}
+
+typedef enum _eWrapMemType_
+{
+    WRAP_TYPE_CLEANUP,
+    WRAP_TYPE_GET_USER_PAGES,
+    WRAP_TYPE_FIND_VMA_PAGES,
+    WRAP_TYPE_FIND_VMA_PFN
+} eWrapMemType;
+
+typedef struct _sWrapMemInfo_
+{
+    eWrapMemType eType;
+    IMG_INT iNumPages;
+    struct page **ppsPages;
+    IMG_SYS_PHYADDR *psPhysAddr;
+    IMG_INT iPageOffset;
+    IMG_INT iContiguous;
+#if defined(DEBUG)
+    IMG_UINT32 ulStartAddr;
+    IMG_UINT32 ulBeyondEndAddr;
+    struct vm_area_struct *psVMArea;
+#endif
+       IMG_BOOL bWrapWorkaround;
+} sWrapMemInfo;
+
+static IMG_VOID CheckPagesContiguous(sWrapMemInfo *psInfo)
+{
+    IMG_INT i;
+    IMG_UINT32 ui32AddrChk;
+
+    BUG_ON(psInfo == IMG_NULL);
+
+    psInfo->iContiguous = 1;
+
+    for (i = 0, ui32AddrChk = psInfo->psPhysAddr[0].uiAddr;
+        i < psInfo->iNumPages;
+        i++, ui32AddrChk += PAGE_SIZE)
+    {
+        if (psInfo->psPhysAddr[i].uiAddr != ui32AddrChk)
+        {
+            psInfo->iContiguous = 0;
+            break;
+        }
+    }
+}
+
+static struct page *CPUVAddrToPage(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr)
+{
+    pgd_t *psPGD;
+    pud_t *psPUD;
+    pmd_t *psPMD;
+    pte_t *psPTE;
+    struct mm_struct *psMM = psVMArea->vm_mm;
+    IMG_UINT32 ulPFN;
+    spinlock_t *psPTLock;
+    struct page *psPage;
+
+    psPGD = pgd_offset(psMM, ulCPUVAddr);
+    if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+        return NULL;
+
+    psPUD = pud_offset(psPGD, ulCPUVAddr);
+    if (pud_none(*psPUD) || pud_bad(*psPUD))
+        return NULL;
+
+    psPMD = pmd_offset(psPUD, ulCPUVAddr);
+    if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+        return NULL;
+
+    psPage = NULL;
+
+    psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
+    if ((pte_none(*psPTE) != 0) || (pte_present(*psPTE) == 0) || (pte_write(*psPTE) == 0))
+        goto exit_unlock;
+
+    ulPFN = pte_pfn(*psPTE);
+    if (!pfn_valid(ulPFN))
+        goto exit_unlock;
+
+    psPage = pfn_to_page(ulPFN);
+
+    get_page(psPage);
+
+exit_unlock:
+    pte_unmap_unlock(psPTE, psPTLock);  
+
+    return psPage;
+}
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+    sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
+    IMG_INT i;
+
+    BUG_ON(psInfo == IMG_NULL);
+
+    switch (psInfo->eType)
+    {
+        case WRAP_TYPE_CLEANUP:
+            break;
+        case WRAP_TYPE_FIND_VMA_PFN:
+            break;
+        case WRAP_TYPE_GET_USER_PAGES:
+        {
+            for (i = 0; i < psInfo->iNumPages; i++)
+            {
+                struct page *psPage = psInfo->ppsPages[i];
+
+                
+                if (!PageReserved(psPage));
+                {
+                    SetPageDirty(psPage);
+                }
+                page_cache_release(psPage);
+            }
+            break;
+        }
+        case WRAP_TYPE_FIND_VMA_PAGES:
+        {
+            for (i = 0; i < psInfo->iNumPages; i++)
+            {
+                if(psInfo->bWrapWorkaround)
+                    put_page(psInfo->ppsPages[i]);
+                else
+                    put_page_testzero(psInfo->ppsPages[i]);
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR,
+                "OSReleasePhysPageAddr: Unknown wrap type (%d)", psInfo->eType));
+            return PVRSRV_ERROR_GENERIC;
+        }
+    }
+
+    if (psInfo->ppsPages != IMG_NULL)
+    {
+        kfree(psInfo->ppsPages);
+    }
+
+    if (psInfo->psPhysAddr != IMG_NULL)
+    {
+        kfree(psInfo->psPhysAddr);
+    }
+
+    kfree(psInfo);
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr, 
+                                    IMG_UINT32 ui32Bytes, 
+                                    IMG_SYS_PHYADDR *psSysPAddr,
+                                    IMG_HANDLE *phOSWrapMem,
+                                    IMG_BOOL bWrapWorkaround)
+{
+    IMG_UINT32 ulStartAddrOrig = (IMG_UINT32) pvCPUVAddr;
+    IMG_UINT32 ulAddrRangeOrig = (IMG_UINT32) ui32Bytes;
+    IMG_UINT32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
+    IMG_UINT32 ulStartAddr;
+    IMG_UINT32 ulAddrRange;
+    IMG_UINT32 ulBeyondEndAddr;
+    IMG_UINT32 ulAddr;
+    IMG_INT iNumPagesMapped;
+    IMG_INT i;
+    struct vm_area_struct *psVMArea;
+    sWrapMemInfo *psInfo;
+
+    
+    ulStartAddr = ulStartAddrOrig & PAGE_MASK;
+    ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
+    ulAddrRange = ulBeyondEndAddr - ulStartAddr;
+
+    
+    psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
+    if (psInfo == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate information structure"));
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+    memset(psInfo, 0, sizeof(*psInfo));
+    psInfo->bWrapWorkaround = bWrapWorkaround;
+
+#if defined(DEBUG)
+    psInfo->ulStartAddr = ulStartAddrOrig;
+    psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+#endif
+
+    psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
+    psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
+
+    
+    psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
+    if (psInfo->psPhysAddr == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate page array"));           
+        goto error_free;
+    }
+
+    
+    psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages),  GFP_KERNEL);
+    if (psInfo->ppsPages == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate page array"));           
+        goto error_free;
+    }
+
+    
+    down_read(&current->mm->mmap_sem);
+    iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+    up_read(&current->mm->mmap_sem);
+
+    if (iNumPagesMapped >= 0)
+    {
+        
+        if (iNumPagesMapped != psInfo->iNumPages)
+        {
+            PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, iNumPagesMapped));
+
+            
+            for (i = 0; i < iNumPagesMapped; i++)
+            {
+                page_cache_release(psInfo->ppsPages[i]);
+                    
+            }
+            goto error_free;
+        }
+
+        
+        for (i = 0; i < psInfo->iNumPages; i++)
+        {
+            IMG_CPU_PHYADDR CPUPhysAddr;
+
+            CPUPhysAddr.uiAddr = page_to_pfn(psInfo->ppsPages[i]) << PAGE_SHIFT;
+            psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+            psSysPAddr[i] = psInfo->psPhysAddr[i];
+            
+        }
+
+        psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+        goto exit_check;
+    }
+
+    PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), trying something else", iNumPagesMapped));
+    
+    
+    down_read(&current->mm->mmap_sem);
+
+    psVMArea = find_vma(current->mm, ulStartAddrOrig);
+    if (psVMArea == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't find memory region containing start address %lx", ulStartAddrOrig));
+        
+        goto error_release_mmap_sem;
+    }
+#if defined(DEBUG)
+    psInfo->psVMArea = psVMArea;
+#endif
+
+    
+    if (ulStartAddrOrig < psVMArea->vm_start)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Start address %lx is outside of the region returned by find_vma", ulStartAddrOrig));
+        goto error_release_mmap_sem;
+    }
+
+    
+    if (ulBeyondEndAddrOrig > psVMArea->vm_end)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: End address %lx is outside of the region returned by find_vma", ulBeyondEndAddrOrig));
+        goto error_release_mmap_sem;
+    }
+
+    
+    if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags));
+        goto error_release_mmap_sem;
+    }
+
+    
+    if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: No read/write access to memory region (VMA flags: 0x%lx)", psVMArea->vm_flags));
+        goto error_release_mmap_sem;
+    }
+
+    
+    for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+    {
+        struct page *psPage;
+
+        BUG_ON(i >= psInfo->iNumPages);
+
+        psPage = CPUVAddrToPage(psVMArea, ulAddr);
+        if (psPage == NULL)
+        {
+            IMG_INT j;
+
+        PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't lookup page structure for address 0x%lx, trying something else", ulAddr));
+
+            
+            for (j = 0; j < i; j++)
+            {
+                if(psInfo->bWrapWorkaround)
+                    put_page(psInfo->ppsPages[j]);
+                else
+                    put_page_testzero(psInfo->ppsPages[j]);
+            }
+            break;
+        }
+
+        psInfo->ppsPages[i] = psPage;
+    }
+
+    BUG_ON(i > psInfo->iNumPages);
+    if (i == psInfo->iNumPages)
+    {
+        
+        for (i = 0; i < psInfo->iNumPages; i++)
+        {
+            struct page *psPage = psInfo->ppsPages[i];
+            IMG_CPU_PHYADDR CPUPhysAddr;
+
+            
+            CPUPhysAddr.uiAddr = page_to_pfn(psPage) << PAGE_SHIFT;
+
+            psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+            psSysPAddr[i] = psInfo->psPhysAddr[i];
+        }
+
+        psInfo->eType = WRAP_TYPE_FIND_VMA_PAGES;
+    }
+    else
+    {
+#if defined(PVR_SECURE_HANDLES)
+        
+
+        
+        if ((psVMArea->vm_flags & VM_PFNMAP) == 0)
+        {
+        PVR_DPF((PVR_DBG_WARNING,
+            "OSAcquirePhysPageAddr: Region isn't a raw PFN mapping.  Giving up."));
+            goto error_release_mmap_sem;
+        }
+        
+        for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+        {
+            IMG_CPU_PHYADDR CPUPhysAddr;
+
+            CPUPhysAddr.uiAddr = ((ulAddr - psVMArea->vm_start) + (psVMArea->vm_pgoff << PAGE_SHIFT)) & PAGE_MASK;
+
+            psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+            psSysPAddr[i] = psInfo->psPhysAddr[i];
+        }
+        BUG_ON(i != psInfo->iNumPages);
+
+        psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
+
+        
+        PVR_DPF((PVR_DBG_WARNING,
+            "OSAcquirePhysPageAddr: Region can't be locked down"));
+#else
+        PVR_DPF((PVR_DBG_WARNING,
+            "OSAcquirePhysPageAddr: Raw PFN mappings not supported.  Giving up."));
+        goto error_release_mmap_sem;
+#endif 
+    }
+
+    up_read(&current->mm->mmap_sem);
+
+exit_check:
+    CheckPagesContiguous(psInfo);
+
+
+    
+    *phOSWrapMem = (IMG_HANDLE)psInfo;
+
+    return PVRSRV_OK;
+
+error_release_mmap_sem:
+    up_read(&current->mm->mmap_sem);
+error_free:
+    psInfo->eType = WRAP_TYPE_CLEANUP;
+    OSReleasePhysPageAddr((IMG_HANDLE)psInfo);
+    return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    {
+        IMG_UINT32 ui32i;
+
+        psTimerWorkQueue = create_workqueue("pvr_timer");
+        if (psTimerWorkQueue == NULL)
+        {
+           PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));              
+           return PVRSRV_ERROR_GENERIC;
+
+        }
+
+        for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+        {
+            TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i];
+
+           INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack);
+        }
+    }
+#endif
+    return PVRSRV_OK;
+}
+
+IMG_VOID PVROSFuncDeInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    if (psTimerWorkQueue != NULL)
+    {
+       destroy_workqueue(psTimerWorkQueue);
+    }
+#endif
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/osperproc.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/osperproc.c
new file mode 100644 (file)
index 0000000..011c8f3
--- /dev/null
@@ -0,0 +1,113 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+#include "proc.h"
+
+extern IMG_UINT32 gui32ReleasePID;
+
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hBlockAlloc;
+       PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                               sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+                               phOsPrivateData,
+                               &hBlockAlloc,
+                               "Environment per Process Data");
+
+       if (eError != PVRSRV_OK)
+       {
+               *phOsPrivateData = IMG_NULL;
+
+               PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError));
+               return eError;
+       }
+
+       psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+       OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+       psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+       
+       LinuxMMapPerProcessConnect(psEnvPerProc);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       
+       INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
+#endif
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+       if (hOsPrivateData == IMG_NULL)
+       {
+               return PVRSRV_OK;
+       }
+
+       psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+       
+       LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+       
+       RemovePerProcessProcDir(psEnvPerProc);
+
+       eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                               sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+                               hOsPrivateData,
+                               psEnvPerProc->hBlockAlloc);
+       
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError));
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+       return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID)
+{
+       if(!gui32ReleasePID)
+               return NULL;
+       return PVRSRVPerProcessPrivateData(gui32ReleasePID);
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pdump.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pdump.c
new file mode 100644 (file)
index 0000000..11d69d1
--- /dev/null
@@ -0,0 +1,662 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if defined (SUPPORT_SGX)
+#if defined (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+#include "sgxdefs.h"
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "sgxmmu.h"
+#include "mm.h"
+#include "pdump_km.h"
+
+#include <linux/tty.h>                 
+
+static IMG_BOOL PDumpWriteString2              (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
+static IMG_BOOL PDumpWriteILock                        (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
+static IMG_VOID DbgSetFrame                            (PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
+static IMG_UINT32 DbgGetFrame                  (PDBG_STREAM psStream);
+static IMG_VOID DbgSetMarker                   (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+static IMG_UINT32 DbgWrite                             (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
+
+#define PDUMP_DATAMASTER_PIXEL         (1)
+#define PDUMP_DATAMASTER_EDM           (3)
+
+#define MIN(a,b)       (a > b ? b : a)
+
+#define MAX_FILE_SIZE  0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
+                                                                                               "ScriptStream2",
+                                                                                               "DriverInfoStream"};
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+       PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
+       IMG_UINT32 ui32ParamFileNum;
+
+       IMG_CHAR *pszMsg;
+       IMG_CHAR *pszScript;
+       IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX                        PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX             PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX   PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+
+
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+static inline IMG_BOOL PDumpSuspended(IMG_VOID)
+{
+       return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+                                                                       IMG_UINT32 *pui32MaxLen)
+{
+       *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+       *pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+       if ((!*phScript) || PDumpSuspended())
+       {
+               return PVRSRV_ERROR_GENERIC;
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_HANDLE *phMsg,
+                                                                        IMG_UINT32 *pui32MaxLen)
+{
+       *phMsg = (IMG_HANDLE)gsDBGPdumpState.pszMsg;
+       *pui32MaxLen = SZ_MSG_SIZE_MAX;
+       if ((!*phMsg) || PDumpSuspended())
+       {
+               return PVRSRV_ERROR_GENERIC;
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+                                                                        IMG_UINT32 *pui32MaxLen)
+{
+       *ppszFile = gsDBGPdumpState.pszFile;
+       *pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+       if ((!*ppszFile) || PDumpSuspended())
+       {
+               return PVRSRV_ERROR_GENERIC;
+       }
+       return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
+{
+       return PDumpWriteString2(hScript, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+       IMG_CHAR* pszBuf = hBuf;
+       IMG_UINT32 n;
+       va_list vaArgs;
+
+       va_start(vaArgs, pszFormat);
+
+       n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+       va_end(vaArgs);
+
+       if (n>=ui32ScriptSizeMax || n==-1)      
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+               return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+       IMG_UINT32 n;
+
+       n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+       if (n>=ui32ScriptSizeMax || n==-1)      
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+               return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+       }
+
+       return PVRSRV_OK;
+}
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+       
+}
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+       IMG_UINT32 n;
+       va_list vaArgs;
+
+       va_start(vaArgs, pszFormat);
+
+       n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+       va_end(vaArgs);
+
+       if (n>=ui32ScriptSizeMax || n==-1)      
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+               return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+       }
+
+       return PVRSRV_OK;
+}
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+       IMG_CHAR* pszBuf = hBuffer;
+       IMG_UINT32 ui32Count = 0;
+
+       while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+       {
+               ui32Count++;
+       }
+       return(ui32Count);
+}
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+       IMG_UINT32 ui32Count = 0;
+       IMG_CHAR* pszBuf = hBuffer;
+
+       
+       ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+       
+       if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+       {
+               pszBuf[ui32Count] = '\n';
+               ui32Count++;
+               pszBuf[ui32Count] = '\0';
+       }
+       if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
+       {
+               pszBuf[ui32Count-1] = '\r';
+               pszBuf[ui32Count] = '\n';
+               ui32Count++;
+               pszBuf[ui32Count] = '\0';
+       }
+}
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
+{
+       return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
+}
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
+{
+       PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
+       return gpfnDbgDrv->pfnGetStreamOffset(psStream);
+}
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
+{
+       return gsDBGPdumpState.ui32ParamFileNum;
+}
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
+               IMG_UINT8 *psui8Data,
+               IMG_UINT32 ui32Size,
+               IMG_UINT32 ui32Flags)
+{
+       PDBG_STREAM psStream = (PDBG_STREAM)hStream;
+       return PDumpWriteILock(psStream,
+                                       psui8Data,
+                                       ui32Size,
+                                       ui32Flags);
+}
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+{
+       
+       PVR_UNREFERENCED_PARAMETER(hStream);
+       PVR_UNREFERENCED_PARAMETER(ui32Size);
+       PVR_UNREFERENCED_PARAMETER(ui32Size);
+}
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
+{
+       if(gpfnDbgDrv)
+       {
+               return IMG_TRUE;
+       }
+       return IMG_FALSE;
+}
+
+inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
+{
+       return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+        IMG_HANDLE hOSMemHandle,
+               IMG_UINT32 ui32Offset,
+               IMG_UINT8 *pui8LinAddr,
+               IMG_UINT32 ui32PageSize,
+               IMG_DEV_PHYADDR *psDevPAddr)
+{
+       if(hOSMemHandle)
+       {
+               
+               IMG_CPU_PHYADDR sCpuPAddr;
+
+               PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+               sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+               PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+
+               
+               *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+       }
+       else
+       {
+               IMG_CPU_PHYADDR sCpuPAddr;
+
+               PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+               sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+               *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+       }
+}
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+               IMG_UINT32 ui32Offset,
+               IMG_PUINT8 pui8LinAddr,
+               IMG_UINT32 *pui32PageOffset)
+{
+       if(hOSMemHandle)
+       {
+               
+               IMG_CPU_PHYADDR     sCpuPAddr;
+
+               PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+               sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+           *pui32PageOffset = sCpuPAddr.uiAddr & (HOST_PAGESIZE() -1);
+       }
+       else
+       {
+               PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+               PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+               *pui32PageOffset = (IMG_UINT32)pui8LinAddr & (HOST_PAGESIZE() - 1);
+       }
+}
+
+
+
+IMG_VOID PDumpInit(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       
+       if (!gpfnDbgDrv)
+       {
+               DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+
+
+
+               
+               if (gpfnDbgDrv == IMG_NULL)
+               {
+                       return;
+               }
+
+               if(!gsDBGPdumpState.pszFile)
+               {
+                       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
+                               "Filename string") != PVRSRV_OK)
+                       {
+                               goto init_failed;
+                       }
+               }
+
+               if(!gsDBGPdumpState.pszMsg)
+               {
+                       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
+                               "Message string") != PVRSRV_OK)
+                       {
+                               goto init_failed;
+                       }
+               }
+
+               if(!gsDBGPdumpState.pszScript)
+               {
+                       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
+                               "Script string") != PVRSRV_OK)
+                       {
+                               goto init_failed;
+                       }
+               }
+
+               for(i=0; i < PDUMP_NUM_STREAMS; i++)
+               {
+                       gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+                                                                                                               DEBUG_CAPMODE_FRAMED,
+                                                                                                               DEBUG_OUTMODE_STREAMENABLE,
+                                                                                                               0,
+                                                                                                               10);
+
+                       gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
+                       gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
+               }
+
+               PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+               PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FILE);
+               PDUMPCOMMENT("Start of Init Phase");
+       }
+
+       return;
+
+init_failed:
+
+       if(gsDBGPdumpState.pszFile)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+               gsDBGPdumpState.pszFile = IMG_NULL;
+       }
+
+       if(gsDBGPdumpState.pszScript)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+               gsDBGPdumpState.pszScript = IMG_NULL;
+       }
+
+       if(gsDBGPdumpState.pszMsg)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+               gsDBGPdumpState.pszMsg = IMG_NULL;
+       }
+
+       gpfnDbgDrv = IMG_NULL;
+}
+
+
+IMG_VOID PDumpDeInit(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       for(i=0; i < PDUMP_NUM_STREAMS; i++)
+       {
+               gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+       }
+
+       if(gsDBGPdumpState.pszFile)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+               gsDBGPdumpState.pszFile = IMG_NULL;
+       }
+
+       if(gsDBGPdumpState.pszScript)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+               gsDBGPdumpState.pszScript = IMG_NULL;
+       }
+
+       if(gsDBGPdumpState.pszMsg)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+               gsDBGPdumpState.pszMsg = IMG_NULL;
+       }
+
+       gpfnDbgDrv = IMG_NULL;
+}
+
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       if (gpfnDbgDrv)
+       {
+               PDUMPCOMMENT("Start Init Phase");
+               for(i=0; i < PDUMP_NUM_STREAMS; i++)
+               {
+                       gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
+               }
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       if (gpfnDbgDrv)
+       {
+               PDUMPCOMMENT("Stop Init Phase");
+
+               for(i=0; i < PDUMP_NUM_STREAMS; i++)
+               {
+                       gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
+               }
+       }
+       return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+       return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+       if (PDumpSuspended())
+       {
+               return IMG_FALSE;
+       }
+       return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
+{
+       IMG_UINT32      ui32Stream;
+
+       for     (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+       {
+               if      (gsDBGPdumpState.psStream[ui32Stream])
+               {
+                       DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpGetFrameKM(IMG_PUINT32 pui32Frame)
+{
+       *pui32Frame = DbgGetFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+
+       return PVRSRV_OK;
+}
+
+
+
+static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+       return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
+}
+
+
+static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
+{
+       IMG_UINT32 ui32Written = 0;
+       IMG_UINT32 ui32Off = 0;
+
+       if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
+       {
+               return IMG_TRUE;
+       }
+
+
+       
+
+       if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
+       {
+               IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
+
+               if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+               {
+                       if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
+                       {
+                               DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
+                               gsDBGPdumpState.ui32ParamFileNum++;
+                       }
+               }
+       }
+
+
+       while (((IMG_UINT32) ui32Count > 0) && (ui32Written != 0xFFFFFFFF))
+       {
+               ui32Written = DbgWrite(psStream, &pui8Data[ui32Off], ui32Count, ui32Flags);
+
+               
+
+
+               if (ui32Written == 0)
+               {
+                       OSReleaseThreadQuanta();
+               }
+
+               if (ui32Written != 0xFFFFFFFF)
+               {
+                       ui32Off += ui32Written;
+                       ui32Count -= ui32Written;
+               }
+       }
+
+       if (ui32Written == 0xFFFFFFFF)
+       {
+               return IMG_FALSE;
+       }
+
+       return IMG_TRUE;
+}
+
+static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+       gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+
+static IMG_UINT32 DbgGetFrame(PDBG_STREAM psStream)
+{
+       return gpfnDbgDrv->pfnGetFrame(psStream);
+}
+
+static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+       gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+static IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+       IMG_UINT32      ui32BytesWritten;
+
+       if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
+       {
+               
+
+               if (((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+                   (psStream->ui32Start == 0xFFFFFFFFUL) &&
+                   (psStream->ui32End == 0xFFFFFFFFUL) &&
+                    psStream->bInitPhaseComplete)
+               {
+                       ui32BytesWritten = ui32BCount;
+               }
+               else
+               {
+                       ui32BytesWritten = gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, 1);
+               }
+       }
+       else
+       {
+               if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
+               {
+                       IMG_UINT32      ui32DbgFlags;
+
+                       ui32DbgFlags = 0;
+                       if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+                       {
+                               ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+                       }
+
+                       ui32BytesWritten = gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, 1, ui32DbgFlags);
+               }
+               else
+               {
+                       ui32BytesWritten = gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, 1);
+               }
+       }
+
+       return ui32BytesWritten;
+}
+
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+       atomic_inc(&gsPDumpSuspended);
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+       atomic_dec(&gsPDumpSuspended);
+}
+
+#endif 
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/private_data.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/private_data.h
new file mode 100644 (file)
index 0000000..0751765
--- /dev/null
@@ -0,0 +1,67 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include <linux/list.h>
+#include <drm/drmP.h>
+#endif
+
+typedef struct
+{
+       
+       IMG_UINT32 ui32OpenPID;
+
+#if defined(PVR_SECURE_FD_EXPORT)
+       
+       IMG_HANDLE hKernelMemInfo;
+#endif 
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       
+       struct list_head sDRMAuthListItem;
+
+       struct drm_file *psDRMFile;
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+       
+       IMG_UINT64 ui64Stamp;
+#endif 
+
+       
+       IMG_HANDLE hBlockAlloc;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+       IMG_PVOID pPriv;        
+#endif
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/proc.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/proc.c
new file mode 100644 (file)
index 0000000..c5760e3
--- /dev/null
@@ -0,0 +1,954 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "linkage.h"
+
+#include "lists.h"
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+
+
+static struct proc_dir_entry * dir;
+
+#ifndef PVR_PROC_USE_SEQ_FILE
+static off_t procDumpSysNodes(IMG_CHAR *buf, size_t size, off_t off);
+static off_t procDumpVersion(IMG_CHAR *buf, size_t size, off_t off);
+#endif 
+
+
+static const IMG_CHAR PVRProcDirRoot[] = "pvr";
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
+
+static struct file_operations pvr_proc_operations =
+{
+       .open           = pvr_proc_open,
+       .read           = seq_read,
+       .write          = pvr_proc_write,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static struct seq_operations pvr_proc_seq_operations =
+{
+       .start =        pvr_proc_seq_start,
+       .next =         pvr_proc_seq_next,
+       .stop =         pvr_proc_seq_stop,
+       .show =         pvr_proc_seq_show,
+};
+
+static struct proc_dir_entry* g_pProcQueue;
+static struct proc_dir_entry* g_pProcVersion;
+static struct proc_dir_entry* g_pProcSysNodes;
+
+#ifdef DEBUG
+static struct proc_dir_entry* g_pProcDebugLevel;
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+static struct proc_dir_entry* g_pProcPowerLevel;
+#endif
+
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+
+#endif
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+{
+    IMG_INT n;
+    size_t space = size - (size_t)off;
+    va_list ap;
+
+    PVR_ASSERT(space >= 0);
+
+    va_start (ap, format);
+
+    n = vsnprintf (buffer+off, space, format, ap);
+
+    va_end (ap);
+    
+    if (n >= (IMG_INT)space || n < 0)
+    {
+       
+        buffer[size - 1] = 0;
+        return (off_t)(size - 1);
+    }
+    else
+    {
+        return (off + (off_t)n);
+    }
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+{
+       
+       if(!off)
+               return (void*)2;
+       return NULL;
+}
+
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+{
+       if(!off)
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+       
+       if(off == 1)
+               return (void*)2;
+
+       return NULL;
+}
+
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
+{
+       IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
+
+       struct seq_file *seq = (struct seq_file*)file->private_data;
+       struct proc_dir_entry* pvr_proc_entry = PDE(inode);
+
+       
+       seq->private = pvr_proc_entry->data;
+       return ret;
+}
+
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t *ppos)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct proc_dir_entry * dp;
+
+       dp = PDE(inode);
+
+       if (!dp->write_proc)
+               return -EIO;
+
+       return dp->write_proc(file, buffer, count, dp->data);
+}
+
+
+static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+       if(handlers->startstop != NULL)
+               handlers->startstop(proc_seq_file, IMG_TRUE);
+       return handlers->off2element(proc_seq_file, *pos);
+}
+
+static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+       if(handlers->startstop != NULL)
+               handlers->startstop(proc_seq_file, IMG_FALSE);
+}
+
+static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+       (*pos)++;
+       if( handlers->next != NULL)
+               return handlers->next( proc_seq_file, v, *pos );
+       return handlers->off2element(proc_seq_file, *pos);
+}
+
+static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+       handlers->show( proc_seq_file,v );
+    return 0;
+}
+
+
+
+static struct proc_dir_entry* CreateProcEntryInDirSeq(
+                                                                          struct proc_dir_entry *pdir,
+                                                                          const IMG_CHAR * name,
+                                                                  IMG_VOID* data,
+                                                                          pvr_next_proc_seq_t next_handler,
+                                                                          pvr_show_proc_seq_t show_handler,
+                                                                          pvr_off2element_proc_seq_t off2element_handler,
+                                                                          pvr_startstop_proc_seq_t startstop_handler,
+                                                                          write_proc_t whandler
+                                                                          )
+{
+
+    struct proc_dir_entry * file;
+       mode_t mode;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+        return NULL;
+    }
+
+       mode = S_IFREG;
+
+    if (show_handler)
+    {
+               mode |= S_IRUGO;
+    }
+
+    if (whandler)
+    {
+               mode |= S_IWUSR;
+    }
+
+       file=create_proc_entry(name, mode, pdir);
+
+    if (file)
+    {
+               PVR_PROC_SEQ_HANDLERS *seq_handlers;
+
+               file->proc_fops = &pvr_proc_operations;
+               file->write_proc = whandler;
+
+               
+               file->data =  kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
+               if(file->data)
+               {
+                       seq_handlers = (PVR_PROC_SEQ_HANDLERS*)file->data;
+                       seq_handlers->next = next_handler;
+                       seq_handlers->show = show_handler;
+                       seq_handlers->off2element = off2element_handler;
+                       seq_handlers->startstop = startstop_handler;
+                       seq_handlers->data = data;
+
+               return file;
+               }
+    }
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+    return 0;
+}
+
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+                                                               const IMG_CHAR * name,
+                                                               IMG_VOID* data,
+                                                               pvr_next_proc_seq_t next_handler,
+                                                               pvr_show_proc_seq_t show_handler,
+                                                               pvr_off2element_proc_seq_t off2element_handler,
+                                                               pvr_startstop_proc_seq_t startstop_handler
+                                                          )
+{
+       return CreateProcEntrySeq(name,
+                                                         data,
+                                                         next_handler,
+                                                         show_handler,
+                                                         off2element_handler,
+                                                         startstop_handler,
+                                                         NULL);
+}
+
+struct proc_dir_entry* CreateProcEntrySeq (
+                                                                                       const IMG_CHAR * name,
+                                                                                       IMG_VOID* data,
+                                                                                       pvr_next_proc_seq_t next_handler,
+                                                                                       pvr_show_proc_seq_t show_handler,
+                                                                                       pvr_off2element_proc_seq_t off2element_handler,
+                                                                                       pvr_startstop_proc_seq_t startstop_handler,
+                                                                                       write_proc_t whandler
+                                                                                 )
+{
+       return CreateProcEntryInDirSeq(
+                                                                  dir,
+                                                                  name,
+                                                                  data,
+                                                                  next_handler,
+                                                                  show_handler,
+                                                                  off2element_handler,
+                                                                  startstop_handler,
+                                                                  NULL
+                                                                 );
+}
+
+
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+                                                                         const IMG_CHAR * name,
+                                                                 IMG_VOID* data,
+                                                                         pvr_next_proc_seq_t next_handler,
+                                                                         pvr_show_proc_seq_t show_handler,
+                                                                         pvr_off2element_proc_seq_t off2element_handler,
+                                                                         pvr_startstop_proc_seq_t startstop_handler,
+                                                                         write_proc_t whandler
+                                                                        )
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+    IMG_UINT32 ui32PID;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
+        return NULL;
+    }
+
+    ui32PID = OSGetCurrentProcessIDKM();
+
+    psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+    if (!psPerProc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
+
+        return NULL;
+    }
+
+    if (!psPerProc->psProcDir)
+    {
+        IMG_CHAR dirname[16];
+        IMG_INT ret;
+
+        ret = snprintf(dirname, sizeof(dirname), "%lu", ui32PID);
+
+               if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+                       return NULL;
+               }
+               else
+               {
+                       psPerProc->psProcDir = proc_mkdir(dirname, dir);
+                       if (!psPerProc->psProcDir)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
+                                               PVRProcDirRoot, ui32PID));
+                               return NULL;
+                       }
+               }
+    }
+
+    return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+                                                                  show_handler,off2element_handler,startstop_handler,whandler);
+}
+
+
+IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
+{
+    if (dir)
+    {
+               void* data = proc_entry->data ;
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, proc_entry->name));
+
+        remove_proc_entry(proc_entry->name, dir);
+               if( data)
+                       kfree( data );
+
+    }
+}
+
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+    psPerProc = LinuxTerminatingProcessPrivateData();
+    if (!psPerProc)
+    {
+        psPerProc = PVRSRVFindPerProcessPrivateData();
+        if (!psPerProc)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+                                    "remove %s, no per process data", proc_entry->name));
+            return;
+        }
+    }
+
+    if (psPerProc->psProcDir)
+    {
+               void* data = proc_entry->data ;
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", proc_entry->name, psPerProc->psProcDir->name));
+
+        remove_proc_entry(proc_entry->name, psPerProc->psProcDir);
+               if(data)
+                       kfree( data );
+    }
+}
+
+#endif 
+
+static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
+                         IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+    pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
+
+    off_t len = pprn (page, (size_t)count, off);
+
+    if (len == END_OF_FILE)
+    {
+        len  = 0;
+        *eof = 1;
+    }
+    else if (!len)             
+    {
+        *start = (IMG_CHAR *) 0;   
+    }
+    else
+    {
+        *start = (IMG_CHAR *) 1;
+    }
+
+    return len;
+}
+
+
+static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    struct proc_dir_entry * file;
+    mode_t mode;
+
+    if (!pdir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDir: parent directory doesn't exist"));
+
+        return -ENOMEM;
+    }
+
+    mode = S_IFREG;
+
+    if (rhandler)
+    {
+       mode |= S_IRUGO;
+    }
+
+    if (whandler)
+    {
+       mode |= S_IWUSR;
+    }
+
+    file = create_proc_entry(name, mode, pdir);
+
+    if (file)
+    {
+               file->read_proc = rhandler;
+               file->write_proc = whandler;
+               file->data = data;
+
+               PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, pdir->name));
+
+        return 0;
+    }
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, pdir->name));
+
+    return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+    IMG_UINT32 ui32PID;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: /proc/%s doesn't exist", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+    ui32PID = OSGetCurrentProcessIDKM();
+
+    psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+    if (!psPerProc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: no per process data"));
+
+        return -ENOMEM;
+    }
+
+    if (!psPerProc->psProcDir)
+    {
+        IMG_CHAR dirname[16];
+        IMG_INT ret;
+
+        ret = snprintf(dirname, sizeof(dirname), "%lu", ui32PID);
+
+               if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+
+                                       return -ENOMEM;
+               }
+               else
+               {
+                       psPerProc->psProcDir = proc_mkdir(dirname, dir);
+                       if (!psPerProc->psProcDir)
+                       {
+                       PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u", PVRProcDirRoot, ui32PID));
+
+                       return -ENOMEM;
+                       }
+               }
+    }
+
+    return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
+{
+    struct proc_dir_entry * file;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+
+        return -ENOMEM;
+    }
+
+    file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
+
+    if (file)
+        return 0;
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+
+    return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntries(IMG_VOID)
+{
+    dir = proc_mkdir (PVRProcDirRoot, NULL);
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+       g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+       g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
+       g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
+
+       if(!g_pProcQueue || !g_pProcVersion || !g_pProcSysNodes)
+#else 
+    if (CreateProcReadEntry("queue", QueuePrintQueues) ||
+               CreateProcReadEntry("version", procDumpVersion) ||
+               CreateProcReadEntry("nodes", procDumpSysNodes))
+#endif 
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+
+#ifdef DEBUG
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+       g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
+                                                                                       ProcSeqShowDebugLevel,
+                                                                                       ProcSeq1ElementOff2Element, NULL,
+                                                                                   PVRDebugProcSetLevel);
+       if(!g_pProcDebugLevel)
+#else 
+       if (CreateProcEntry ("debug_level", PVRDebugProcGetLevel, PVRDebugProcSetLevel, 0))
+#endif 
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+#ifdef PVR_PROC_USE_SEQ_FILE
+       g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
+                                                                                       ProcSeqShowPowerLevel,
+                                                                                       ProcSeq1ElementOff2Element, NULL,
+                                                                                   PVRProcSetPowerLevel);
+       if(!g_pProcPowerLevel)
+#else 
+       if (CreateProcEntry("power_control", PVRProcGetPowerLevel, PVRProcSetPowerLevel, 0))
+#endif
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+#endif
+#endif
+
+    return 0;
+}
+
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+    if (dir)
+    {
+        remove_proc_entry(name, dir);
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
+    }
+}
+
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+    psPerProc = LinuxTerminatingProcessPrivateData();
+    if (!psPerProc)
+    {
+        psPerProc = PVRSRVFindPerProcessPrivateData();
+        if (!psPerProc)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+                                    "remove %s, no per process data", name));
+            return;
+        }
+    }
+
+    if (psPerProc->psProcDir)
+    {
+        remove_proc_entry(name, psPerProc->psProcDir);
+
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name));
+    }
+}
+
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+    if (psPerProc->psProcDir)
+    {
+        while (psPerProc->psProcDir->subdir)
+        {
+            PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
+
+            RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+        }
+        RemoveProcEntry(psPerProc->psProcDir->name);
+    }
+}
+
+IMG_VOID RemoveProcEntries(IMG_VOID)
+{
+#ifdef DEBUG
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq( g_pProcDebugLevel );
+#else 
+    RemoveProcEntry("debug_level");
+#endif 
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq( g_pProcPowerLevel );
+#else 
+    RemoveProcEntry("power_control");
+#endif 
+#endif 
+
+#endif 
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq(g_pProcQueue);
+    RemoveProcEntrySeq(g_pProcVersion);
+       RemoveProcEntrySeq(g_pProcSysNodes);
+#else 
+    RemoveProcEntry("queue");
+    RemoveProcEntry("version");
+    RemoveProcEntry("nodes");
+#endif 
+
+    while (dir->subdir)
+    {
+       PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
+
+       RemoveProcEntry(dir->subdir->name);
+    }
+
+    remove_proc_entry(PVRProcDirRoot, NULL);
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
+{
+       SYS_DATA * psSysData;
+       IMG_CHAR *pszSystemVersionString = "None";
+
+       if(el == PVR_PROC_SEQ_START_TOKEN)
+       {
+               seq_printf( sfile,
+                                               "Version %s (%s) %s\n",
+                                               PVRVERSION_STRING,
+                                               PVR_BUILD_TYPE, PVR_BUILD_DIR);
+               return;
+       }
+
+    SysAcquireData(&psSysData);
+
+    if(psSysData->pszVersionString)
+       {
+       pszSystemVersionString = psSysData->pszVersionString;
+    }
+
+       seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
+}
+
+#else
+
+static off_t procDumpVersion(IMG_CHAR *buf, size_t size, off_t off)
+{
+    SYS_DATA *psSysData;
+
+    if (off == 0)
+    {
+       return printAppend(buf, size, 0,
+                                               "Version %s (%s) %s\n",
+                                               PVRVERSION_STRING,
+                                               PVR_BUILD_TYPE, PVR_BUILD_DIR);
+    }
+
+    SysAcquireData(&psSysData)
+
+    if (off == 1)
+    {
+        IMG_CHAR *pszSystemVersionString = "None";
+
+        if(psSysData->pszVersionString)
+        {
+            pszSystemVersionString = psSysData->pszVersionString;
+        }
+
+        if(strlen(pszSystemVersionString)
+            + strlen("System Version String: \n")
+            + 1 > size)
+        {
+            return 0;
+        }
+        return printAppend(buf, size, 0,
+                            "System Version String: %s\n",
+                            pszSystemVersionString);
+    }
+
+    return END_OF_FILE;
+}
+
+#endif 
+
+
+static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+    switch (deviceType)
+    {
+        default:
+        {
+            static IMG_CHAR text[10];
+
+            sprintf(text, "?%x", (IMG_UINT)deviceType);
+
+            return text;
+        }
+    }
+}
+
+
+static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
+{
+    switch (deviceClass)
+    {
+       case PVRSRV_DEVICE_CLASS_3D:
+       {
+           return "3D";
+       }
+       case PVRSRV_DEVICE_CLASS_DISPLAY:
+       {
+           return "display";
+       }
+       case PVRSRV_DEVICE_CLASS_BUFFER:
+       {
+           return "buffer";
+       }
+       default:
+       {
+           static IMG_CHAR text[10];
+
+           sprintf(text, "?%x", (IMG_UINT)deviceClass);
+           return text;
+       }
+    }
+}
+
+IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
+{
+       off_t *pOff = va_arg(va, off_t*);
+       if (--(*pOff))
+       {
+               return IMG_NULL;
+       }
+       else
+       {
+               return psNode;
+       }
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
+{
+       SYS_DATA * psSysData;
+    PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE*)el;
+
+       if(el == PVR_PROC_SEQ_START_TOKEN)
+       {
+               seq_printf( sfile,
+                                               "Registered nodes\n"
+                                               "Addr     Type     Class    Index Ref pvDev     Size Res\n");
+               return;
+       }
+
+    SysAcquireData(&psSysData);
+
+       seq_printf( sfile,
+                                 "%p %-8s %-8s %4d  %2lu  %p  %3lu  %p\n",
+                                 psDevNode,
+                                 deviceTypeToString(psDevNode->sDevId.eDeviceType),
+                                 deviceClassToString(psDevNode->sDevId.eDeviceClass),
+                                 psDevNode->sDevId.eDeviceClass,
+                                 psDevNode->ui32RefCount,
+                                 psDevNode->pvDevice,
+                                 psDevNode->ui32pvDeviceSize,
+                                 psDevNode->hResManContext);
+
+}
+
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
+{
+    SYS_DATA *psSysData;
+    PVRSRV_DEVICE_NODE *psDevNode;
+       if(!off)
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+    SysAcquireData(&psSysData);
+
+    
+       psDevNode = (PVRSRV_DEVICE_NODE*)
+                               List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                                       DecOffPsDev_AnyVaCb,
+                                                                                                       &off);
+
+       
+       return (void*)psDevNode;
+}
+
+#else 
+
+static
+off_t procDumpSysNodes(IMG_CHAR *buf, size_t size, off_t off)
+{
+    SYS_DATA                   *psSysData;
+    PVRSRV_DEVICE_NODE *psDevNode;
+    off_t                              len;
+
+    
+    if (size < 80)
+    {
+               return 0;
+    }
+
+    if (off == 0)
+    {
+               return printAppend(buf, size, 0,
+                                               "Registered nodes\n"
+                                               "Addr     Type     Class    Index Ref pvDev     Size Res\n");
+    }
+
+    SysAcquireData(&psSysData);
+
+    
+       psDevNode = (PVRSRV_DEVICE_NODE*)
+                               List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                                       DecOffPsDev_AnyVaCb,
+                                                                                                       &off);
+
+    if (!psDevNode)
+    {
+               return END_OF_FILE;
+    }
+
+    len = printAppend(buf, size, 0,
+                                 "%p %-8s %-8s %4d  %2lu  %p  %3lu  %p\n",
+                                 psDevNode,
+                                 deviceTypeToString(psDevNode->sDevId.eDeviceType),
+                                 deviceClassToString(psDevNode->sDevId.eDeviceClass),
+                                 psDevNode->sDevId.eDeviceClass,
+                                 psDevNode->ui32RefCount,
+                                 psDevNode->pvDevice,
+                                 psDevNode->ui32pvDeviceSize,
+                                 psDevNode->hResManContext);
+    return (len);
+}
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/proc.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/proc.h
new file mode 100644 (file)
index 0000000..3200961
--- /dev/null
@@ -0,0 +1,115 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __SERVICES_PROC_H__
+#define __SERVICES_PROC_H__
+
+#include <asm/system.h>                
+#include <linux/proc_fs.h>     
+#include <linux/seq_file.h> 
+
+#define END_OF_FILE (off_t) -1
+
+typedef off_t (pvr_read_proc_t)(IMG_CHAR *, size_t, off_t);
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
+typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
+typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
+typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
+
+typedef struct _PVR_PROC_SEQ_HANDLERS_ {
+       pvr_next_proc_seq_t *next;      
+       pvr_show_proc_seq_t *show;      
+       pvr_off2element_proc_seq_t *off2element;
+       pvr_startstop_proc_seq_t *startstop;
+       IMG_VOID *data;
+} PVR_PROC_SEQ_HANDLERS;
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
+
+
+#endif 
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+       __attribute__((format(printf, 4, 5)));
+
+IMG_INT CreateProcEntries(IMG_VOID);
+
+IMG_INT CreateProcReadEntry (const IMG_CHAR * name, pvr_read_proc_t handler);
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemoveProcEntries(IMG_VOID);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+struct proc_dir_entry* CreateProcReadEntrySeq (
+                                                               const IMG_CHAR* name, 
+                                                               IMG_VOID* data,
+                                                               pvr_next_proc_seq_t next_handler, 
+                                                               pvr_show_proc_seq_t show_handler,
+                                                               pvr_off2element_proc_seq_t off2element_handler,
+                                                               pvr_startstop_proc_seq_t startstop_handler
+                                                          );
+
+struct proc_dir_entry* CreateProcEntrySeq (
+                                                               const IMG_CHAR* name, 
+                                                               IMG_VOID* data,
+                                                               pvr_next_proc_seq_t next_handler, 
+                                                               pvr_show_proc_seq_t show_handler,
+                                                               pvr_off2element_proc_seq_t off2element_handler,
+                                                               pvr_startstop_proc_seq_t startstop_handler,
+                                                               write_proc_t whandler
+                                                          );
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+                                                               const IMG_CHAR* name, 
+                                                               IMG_VOID* data,
+                                                               pvr_next_proc_seq_t next_handler, 
+                                                               pvr_show_proc_seq_t show_handler,
+                                                               pvr_off2element_proc_seq_t off2element_handler,
+                                                               pvr_startstop_proc_seq_t startstop_handler,
+                                                               write_proc_t whandler
+                                                          );
+
+
+IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry);
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry);
+
+#endif 
+
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_bridge_k.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_bridge_k.c
new file mode 100644 (file)
index 0000000..423d631
--- /dev/null
@@ -0,0 +1,652 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "pvr_bridge_km.h"
+
+#include <linux/mutex.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+
+#ifdef MODULE_TEST
+#include "pvr_test_bridge.h"
+#include "kern_test.h"
+#endif
+
+
+#if defined(SUPPORT_DRI_DRM)
+#define        PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define        PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+static struct proc_dir_entry *g_ProcBridgeStats =0;
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
+
+#else 
+static off_t printLinuxBridgeStats(IMG_CHAR * buffer, size_t size, off_t off);
+#endif 
+
+#endif
+
+extern struct mutex gPVRSRVLock;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+static IMG_UINT64 ui64Stamp;
+#endif 
+
+PVRSRV_ERROR
+LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+       {
+               IMG_INT iStatus;
+#ifdef PVR_PROC_USE_SEQ_FILE
+               g_ProcBridgeStats = CreateProcReadEntrySeq(
+                                                                                                 "bridge_stats", 
+                                                                                                 NULL,
+                                                                                                 ProcSeqNextBridgeStats,
+                                                                                                 ProcSeqShowBridgeStats,
+                                                                                                 ProcSeqOff2ElementBridgeStats,
+                                                                                                 ProcSeqStartstopBridgeStats
+                                                                                                );
+               iStatus = !g_ProcBridgeStats ? -1 : 0;
+#else  
+               iStatus = CreateProcReadEntry("bridge_stats", printLinuxBridgeStats);
+#endif 
+               
+               if(iStatus!=0)
+               {
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+       }
+#endif
+       return CommonBridgeInit();
+}
+
+IMG_VOID
+LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq(g_ProcBridgeStats);
+#else
+       RemoveProcEntry("bridge_stats");
+#endif
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start) 
+{
+       if(start) 
+       {
+               mutex_lock(&gPVRSRVLock);
+       }
+       else
+       {
+               mutex_unlock(&gPVRSRVLock);
+       }
+}
+
+
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
+{
+       if(!off) 
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+       if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+       {
+               return (void*)0;
+       }
+
+
+       return (void*)&g_BridgeDispatchTable[off-1];
+}
+
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
+{
+       return ProcSeqOff2ElementBridgeStats(sfile,off);
+}
+
+
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
+{
+       PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
+
+       if(el == PVR_PROC_SEQ_START_TOKEN) 
+       {
+               seq_printf(sfile,
+                                                 "Total ioctl call count = %lu\n"
+                                                 "Total number of bytes copied via copy_from_user = %lu\n"
+                                                 "Total number of bytes copied via copy_to_user = %lu\n"
+                                                 "Total number of bytes copied via copy_*_user = %lu\n\n"
+                                                 "%-45s | %-40s | %10s | %20s | %10s\n",
+                                                 g_BridgeGlobalStats.ui32IOCTLCount,
+                                                 g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+                                                 g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+                                                 g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+                                                 "Bridge Name",
+                                                 "Wrapper Function",
+                                                 "Call Count",
+                                                 "copy_from_user Bytes",
+                                                 "copy_to_user Bytes"
+                                                );
+               return;
+       }
+
+       seq_printf(sfile,
+                                  "%-45s   %-40s   %-10lu   %-20lu   %-10lu\n",
+                                  psEntry->pszIOCName,
+                                  psEntry->pszFunctionName,
+                                  psEntry->ui32CallCount,
+                                  psEntry->ui32CopyFromUserTotalBytes,
+                                  psEntry->ui32CopyToUserTotalBytes);
+}
+
+#else 
+
+static off_t
+printLinuxBridgeStats(IMG_CHAR * buffer, size_t count, off_t off)
+{
+       PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry;
+       off_t Ret;
+
+       mutex_lock(&gPVRSRVLock);
+
+       if(!off)
+       {
+               if(count < 500)
+               {
+                       Ret = 0;
+                       goto unlock_and_return;
+               }
+               Ret = printAppend(buffer, count, 0,
+                                                 "Total ioctl call count = %lu\n"
+                                                 "Total number of bytes copied via copy_from_user = %lu\n"
+                                                 "Total number of bytes copied via copy_to_user = %lu\n"
+                                                 "Total number of bytes copied via copy_*_user = %lu\n\n"
+                                                 "%-45s | %-40s | %10s | %20s | %10s\n",
+                                                 g_BridgeGlobalStats.ui32IOCTLCount,
+                                                 g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+                                                 g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+                                                 g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+                                                 "Bridge Name",
+                                                 "Wrapper Function",
+                                                 "Call Count",
+                                                 "copy_from_user Bytes",
+                                                 "copy_to_user Bytes"
+                                                );
+               goto unlock_and_return;
+       }
+
+       if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+       {
+               Ret = END_OF_FILE;
+               goto unlock_and_return;
+       }
+
+       if(count < 300)
+       {
+               Ret = 0;
+               goto unlock_and_return;
+       }
+
+       psEntry = &g_BridgeDispatchTable[off-1];
+       Ret =  printAppend(buffer, count, 0,
+                                          "%-45s   %-40s   %-10lu   %-20lu   %-10lu\n",
+                                          psEntry->pszIOCName,
+                                          psEntry->pszFunctionName,
+                                          psEntry->ui32CallCount,
+                                          psEntry->ui32CopyFromUserTotalBytes,
+                                          psEntry->ui32CopyToUserTotalBytes);
+
+unlock_and_return:
+       mutex_unlock(&gPVRSRVLock);
+       return Ret;
+}
+#endif 
+#endif 
+
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT
+PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+IMG_INT32
+PVRSRV_BridgeDispatchKM(struct file *pFile, IMG_UINT unref__ ioctlCmd, IMG_UINT32 arg)
+#endif
+{
+       IMG_UINT32 cmd;
+#if !defined(SUPPORT_DRI_DRM)
+       PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+       PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+       PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+       IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+       PVRSRV_PER_PROCESS_DATA *psPerProc;
+       IMG_INT err = -EFAULT;
+
+       mutex_lock(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+       PVR_UNREFERENCED_PARAMETER(dev);
+
+       psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+       PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+       PVR_UNREFERENCED_PARAMETER(ioctlCmd);
+
+       psBridgePackageKM = &sBridgePackageKM;
+
+       if(!OSAccessOK(PVR_VERIFY_WRITE,
+                                  psBridgePackageUM,
+                                  sizeof(PVRSRV_BRIDGE_PACKAGE)))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+                                __FUNCTION__));
+
+               goto unlock_and_return;
+       }
+       
+       
+       if(OSCopyFromUser(IMG_NULL,
+                                         psBridgePackageKM,
+                                         psBridgePackageUM,
+                                         sizeof(PVRSRV_BRIDGE_PACKAGE))
+         != PVRSRV_OK)
+       {
+               goto unlock_and_return;
+       }
+#endif
+
+       cmd = psBridgePackageKM->ui32BridgeID;
+
+#if defined(MODULE_TEST)
+       switch (cmd)
+       {
+               case PVRSRV_BRIDGE_SERVICES_TEST_MEM1:
+                       {
+                               PVRSRV_ERROR eError = MemTest1();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+               case PVRSRV_BRIDGE_SERVICES_TEST_MEM2:
+                       {
+                               PVRSRV_ERROR eError = MemTest2();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE:
+                       {
+                               PVRSRV_ERROR eError = ResourceTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT:
+                       {
+                               PVRSRV_ERROR eError = EventObjectTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING:
+                       {
+                               PVRSRV_ERROR eError = MemMappingTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID:
+                       {
+                               PVRSRV_ERROR eError = ProcessIDTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS:
+                       {
+                               PVRSRV_ERROR eError = ClockusWaitusTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_TIMER:
+                       {
+                               PVRSRV_ERROR eError = TimerTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV:
+                       {
+                               PVRSRV_ERROR eError = PrivSrvTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+               case PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA:
+               {
+                       IMG_UINT32               ui32PID;
+                       PVRSRV_PER_PROCESS_DATA *psPerProc;
+                       PVRSRV_ERROR eError;
+                       
+                       ui32PID = OSGetCurrentProcessIDKM();
+               
+                       PVRSRVTrace("PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA %d", ui32PID);
+                       
+                       psPerProc = PVRSRVPerProcessData(ui32PID);
+                                               
+                       eError = CopyDataTest(psBridgePackageKM->pvParamIn, psBridgePackageKM->pvParamOut, psPerProc);
+                       
+                       *(PVRSRV_ERROR*)psBridgePackageKM->pvParamOut = eError;
+                       err = 0;
+                       goto unlock_and_return;
+               }
+
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT:
+                       {
+                               PVRSRV_ERROR eError = PowerMgmtTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+       }
+#endif
+       
+       if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
+       {
+               PVRSRV_ERROR eError;
+
+               eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+                                                                       (IMG_PVOID *)&psPerProc,
+                                                                       psBridgePackageKM->hKernelServices,
+                                                                       PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+                                        __FUNCTION__, eError));
+                       goto unlock_and_return;
+               }
+
+               if(psPerProc->ui32PID != ui32PID)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+                                        "belonging to process %d", __FUNCTION__, ui32PID,
+                                        psPerProc->ui32PID));
+                       goto unlock_and_return;
+               }
+       }
+       else
+       {
+               
+               psPerProc = PVRSRVPerProcessData(ui32PID);
+               if(psPerProc == IMG_NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+                                        "Couldn't create per-process data area"));
+                       goto unlock_and_return;
+               }
+       }
+
+       psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+#if defined(PVR_SECURE_FD_EXPORT)
+       switch(cmd)
+       {
+               case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+               {
+                       PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+                       if(psPrivateData->hKernelMemInfo)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo "
+                                                "per file descriptor", __FUNCTION__));
+                               err = -EINVAL;
+                               goto unlock_and_return;
+                       }
+                       break;
+               }
+
+               case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+               {
+                       PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN =
+                               (PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn;
+                       PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+                       if(!psPrivateData->hKernelMemInfo)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no "
+                                                "associated MemInfo handle", __FUNCTION__));
+                               err = -EINVAL;
+                               goto unlock_and_return;
+                       }
+
+                       psMapDevMemIN->hKernelMemInfo = psPrivateData->hKernelMemInfo;
+                       break;
+               }
+
+               default:
+               {
+                       PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+                       if(psPrivateData->hKernelMemInfo)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried "
+                                                "to use privileged service", __FUNCTION__));
+                               goto unlock_and_return;
+                       }
+                       break;
+               }
+       }
+#endif 
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       switch(cmd)
+       {
+               case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+               case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+               {
+                       PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+                       IMG_INT authenticated = pFile->authenticated;
+                       PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+                       if (authenticated)
+                       {
+                               break;
+                       }
+
+                       
+                       psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
+                       if (psEnvPerProc == IMG_NULL)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
+                               err = -EFAULT;
+                               goto unlock_and_return;
+                       }
+
+                       list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
+                       {
+                               struct drm_file *psDRMFile = psPrivateData->psDRMFile;
+
+                               if (pFile->master == psDRMFile->master)
+                               {
+                                       authenticated |= psDRMFile->authenticated;
+                                       if (authenticated)
+                                       {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (!authenticated)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
+                               err = -EPERM;
+                               goto unlock_and_return;
+                       }
+                       break;
+               }
+               default:
+                       break;
+       }
+#endif 
+
+       err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+       if(err != PVRSRV_OK)
+               goto unlock_and_return;
+
+       switch(cmd)
+       {
+#if defined(PVR_SECURE_FD_EXPORT)
+               case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+               {
+                       PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
+                               (PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut;
+                       PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+                       psPrivateData->hKernelMemInfo = psExportDeviceMemOUT->hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+                       psExportDeviceMemOUT->ui64Stamp = psPrivateData->ui64Stamp = ++ui64Stamp;
+#endif
+                       break;
+               }
+#endif 
+
+#if defined(SUPPORT_MEMINFO_IDS)
+               case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+               {
+                       PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+                               (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
+                       PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+                       psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp =     psPrivateData->ui64Stamp;
+                       break;
+               }
+
+               case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+               {
+                       PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+                               (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut;
+                       psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp;
+                       break;
+               }
+#endif 
+
+               default:
+                       break;
+       }
+
+unlock_and_return:
+       mutex_unlock(&gPVRSRVLock);
+       return err;
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_debug.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_debug.c
new file mode 100644 (file)
index 0000000..7b41fc9
--- /dev/null
@@ -0,0 +1,423 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>                 
+#include <linux/mutex.h>
+#include <stdarg.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "linkage.h"
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#define PVR_MAX_FILEPATH_LEN 256
+
+static IMG_UINT32 gPVRDebugLevel = DBGPRIV_WARNING;
+
+#endif 
+
+#define        PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+static struct mutex gsDebugMutexNonIRQ;
+
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
+
+#define        USE_SPIN_LOCK (in_interrupt() || !preemptible())
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+       /* This is broken! */
+       if (USE_SPIN_LOCK)
+       {
+               spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+       }
+       else
+       {
+               mutex_lock(&gsDebugMutexNonIRQ);
+       }
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+       /* and this is even more broken */
+       if (USE_SPIN_LOCK)
+       {
+               spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+       }
+       else
+       {
+               mutex_unlock(&gsDebugMutexNonIRQ);
+       }
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+       if (USE_SPIN_LOCK)
+       {
+               *ppszBuf = gszBufferIRQ;
+               *pui32BufSiz = sizeof(gszBufferIRQ);
+       }
+       else
+       {
+               *ppszBuf = gszBufferNonIRQ;
+               *pui32BufSiz = sizeof(gszBufferNonIRQ);
+       }
+}
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
+{
+       IMG_UINT32 ui32Used;
+       IMG_UINT32 ui32Space;
+       IMG_INT32 i32Len;
+
+       ui32Used = strlen(pszBuf);
+       BUG_ON(ui32Used >= ui32BufSiz);
+       ui32Space = ui32BufSiz - ui32Used;
+
+       i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+       pszBuf[ui32BufSiz - 1] = 0;
+
+       
+       return (i32Len < 0 || i32Len >= ui32Space);
+}
+
+IMG_VOID PVRDPFInit(IMG_VOID)
+{
+    mutex_init(&gsDebugMutexNonIRQ);
+}
+
+IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+       va_list vaArgs;
+       unsigned long ulLockFlags = 0;
+       IMG_CHAR *pszBuf;
+       IMG_UINT32 ui32BufSiz;
+
+       SelectBuffer(&pszBuf, &ui32BufSiz);
+
+       va_start(vaArgs, pszFormat);
+
+       GetBufferLock(&ulLockFlags);
+       strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+
+       if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+       {
+               printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+       }
+       else
+       {
+               printk(KERN_INFO "%s\n", pszBuf);
+       }
+
+       ReleaseBufferLock(ulLockFlags);
+       va_end(vaArgs);
+
+}
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
+{
+       PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
+       BUG();
+}
+
+#endif 
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
+{
+       va_list VArgs;
+       unsigned long ulLockFlags = 0;
+       IMG_CHAR *pszBuf;
+       IMG_UINT32 ui32BufSiz;
+
+       SelectBuffer(&pszBuf, &ui32BufSiz);
+
+       va_start(VArgs, pszFormat);
+
+       GetBufferLock(&ulLockFlags);
+
+       strncpy(pszBuf, "PVR: ", (ui32BufSiz -1));
+
+       if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+       {
+               printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+       }
+       else
+       {
+               printk(KERN_INFO "%s\n", pszBuf);
+       }
+       
+       ReleaseBufferLock(ulLockFlags);
+
+       va_end(VArgs);
+}
+
+#endif 
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
+{
+               va_list VArgs;
+               IMG_BOOL bTrunc;
+
+               va_start (VArgs, pszFormat);
+               
+               bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+               va_end (VArgs);
+
+               return bTrunc;
+}
+
+IMG_VOID PVRSRVDebugPrintf     (
+                                               IMG_UINT32      ui32DebugLevel,
+                                               const IMG_CHAR* pszFullFileName,
+                                               IMG_UINT32      ui32Line,
+                                               const IMG_CHAR* pszFormat,
+                                               ...
+                                       )
+{
+       IMG_BOOL bTrace, bDebug;
+       const IMG_CHAR *pszFileName = pszFullFileName;  
+       IMG_CHAR *pszLeafName;  
+               
+       bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+       bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+       if (bTrace || bDebug)
+       {
+               va_list vaArgs;
+               unsigned long ulLockFlags = 0;
+               IMG_CHAR *pszBuf;
+               IMG_UINT32 ui32BufSiz;
+
+               SelectBuffer(&pszBuf, &ui32BufSiz);
+
+               va_start(vaArgs, pszFormat);
+
+               GetBufferLock(&ulLockFlags);
+
+               
+               if (bDebug)
+               {
+                       switch(ui32DebugLevel)
+                       {
+                               case DBGPRIV_FATAL:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               case DBGPRIV_ERROR:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               case DBGPRIV_WARNING:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               case DBGPRIV_MESSAGE:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               case DBGPRIV_VERBOSE:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               default:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1));
+                                       break;
+                               }
+                       }
+               }
+               else
+               {
+                       strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+               }
+
+               if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+               {
+                       printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+               }
+               else
+               {
+                       
+                       if (!bTrace)
+                       {
+#ifdef DEBUG_LOG_PATH_TRUNCATE
+                               
+                               static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
+
+                               IMG_CHAR* pszTruncIter;
+                               IMG_CHAR* pszTruncBackInter;
+       
+                               
+                               pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
+  
+                               
+                               strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
+
+                               if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
+                                       IMG_CHAR szTruncateMassage[] = "FILENAME TRUNCATED";
+                                       strcpy(szFileNameRewrite + (PVR_MAX_FILEPATH_LEN - 1 - strlen(szTruncateMassage)), szTruncateMassage);
+                               }
+
+                               pszTruncIter = szFileNameRewrite;
+                               while(*pszTruncIter++ != 0) 
+                               {
+                                       IMG_CHAR* pszNextStartPoint;
+                                       
+                                       if(
+                                          !( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) && 
+                                                ( *(pszTruncIter-1) == '.') &&
+                                                ( *(pszTruncIter-2) == '.') &&
+                                                ( *(pszTruncIter-3) == '/') )  
+                                          ) continue;
+  
+                                       
+                                       pszTruncBackInter = pszTruncIter - 3;
+                                       while(*(--pszTruncBackInter) != '/') 
+                                       {
+                                               if(pszTruncBackInter <= szFileNameRewrite) break;
+                                       }
+                                       pszNextStartPoint = pszTruncBackInter;
+
+                                       
+                                       while(*pszTruncIter != 0) 
+                                       {
+                                               *pszTruncBackInter++ = *pszTruncIter++;
+                                       }
+                                       *pszTruncBackInter = 0;
+
+                                       
+                                       pszTruncIter = pszNextStartPoint;
+                               }
+
+                               pszFileName = szFileNameRewrite;
+                               
+                               if(*pszFileName == '/') pszFileName++;
+#endif
+
+#if !defined(__sh__)
+                               pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '\\');
+       
+                               if (pszLeafName)
+                               {
+                                       pszFileName = pszLeafName;
+                       } 
+#endif 
+
+                               if (BAppend(pszBuf, ui32BufSiz, " [%lu, %s]", ui32Line, pszFileName))
+                               {
+                                       printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+                               }
+                               else
+                               {
+                                       printk(KERN_INFO "%s\n", pszBuf);
+                               }
+                       }
+                       else
+                       {
+                               printk(KERN_INFO "%s\n", pszBuf);
+                       }
+               }
+
+               ReleaseBufferLock(ulLockFlags);
+
+               va_end (vaArgs);
+       }
+}
+
+#endif 
+
+#if defined(DEBUG)
+
+IMG_VOID PVRDebugSetLevel(IMG_UINT32 uDebugLevel)
+{
+       printk(KERN_INFO "PVR: Setting Debug Level = 0x%x\n",(IMG_UINT)uDebugLevel);
+
+       gPVRDebugLevel = uDebugLevel;
+}
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+#define        _PROC_SET_BUFFER_SZ             2
+       IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+
+       if (count != _PROC_SET_BUFFER_SZ)
+       {
+               return -EINVAL;
+       }
+       else
+       {
+               if (copy_from_user(data_buffer, buffer, count))
+                       return -EINVAL;
+               if (data_buffer[count - 1] != '\n')
+                       return -EINVAL;
+               PVRDebugSetLevel(data_buffer[0] - '0');
+       }
+       return (count);
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)    
+{
+       seq_printf(sfile, "%lu\n", gPVRDebugLevel);
+}
+
+#else 
+IMG_INT PVRDebugProcGetLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+       if (off == 0) {
+               *start = (IMG_CHAR *)1;
+               return printAppend(page, count, 0, "%lu\n", gPVRDebugLevel);
+       }
+       *eof = 1;
+       return 0;
+}
+#endif 
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_drm.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_drm.c
new file mode 100644 (file)
index 0000000..fadd13c
--- /dev/null
@@ -0,0 +1,302 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/mutex.h>
+#include <asm/ioctl.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mm.h"
+#include "mmap.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "pvr_bridge.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "pvrversion.h"
+#include "lock.h"
+#include "linkage.h"
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#define        MAKENAME_HELPER(x, y) x ## y
+#define        MAKENAME(x, y) MAKENAME_HELPER(x, y)
+
+#define PVR_DRM_NAME   "pvrsrvkm"
+#define PVR_DRM_DESC   "Imagination Technologies PVR DRM"
+
+#define PVR_PCI_IDS \
+       {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
+struct pci_dev *gpsPVRLDMDev;
+struct drm_device *gpsPVRDRMDev;
+
+#define PVR_DRM_FILE struct drm_file *
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static struct pci_device_id asPciIdList[] = {
+       PVR_PCI_IDS
+};
+#endif
+
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
+{
+       IMG_INT iRes;
+
+       PVR_TRACE(("PVRSRVDrmLoad"));
+
+       gpsPVRDRMDev = dev;
+       gpsPVRLDMDev = dev->pdev;
+
+#if defined(PDUMP)
+       iRes = dbgdrv_init();
+       if (iRes != 0)
+       {
+               return iRes;
+       }
+#endif
+       
+       iRes = PVRCore_Init();
+       if (iRes != 0)
+       {
+               goto exit_dbgdrv_cleanup;
+       }
+
+#if defined(DISPLAY_CONTROLLER)
+       iRes = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(dev);
+       if (iRes != 0)
+       {
+               goto exit_pvrcore_cleanup;
+       }
+#endif
+       return 0;
+
+#if defined(DISPLAY_CONTROLLER)
+exit_pvrcore_cleanup:
+       PVRCore_Cleanup();
+#endif
+exit_dbgdrv_cleanup:
+#if defined(PDUMP)
+       dbgdrv_cleanup();
+#endif
+       return iRes;
+}
+
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev)
+{
+       PVR_TRACE(("PVRSRVDrmUnload"));
+
+#if defined(DISPLAY_CONTROLLER)
+       PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev);
+#endif
+
+       PVRCore_Cleanup();
+
+#if defined(PDUMP)
+       dbgdrv_cleanup();
+#endif
+
+       return 0;
+}
+
+IMG_INT PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file)
+{
+       return PVRSRVOpen(dev, file);
+}
+
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+{
+       PVRSRVRelease(dev, file);
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+       return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+IMG_INT
+PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+       return 0;
+}
+#endif
+
+static IMG_INT
+PVRDRMPCIBusIDField(struct drm_device *dev, IMG_UINT32 *pui32Field, IMG_UINT32 ui32FieldType)
+{
+       struct pci_dev *psPCIDev = (struct pci_dev *)dev->pdev;
+
+       switch (ui32FieldType)
+       {
+               case PVR_DRM_PCI_DOMAIN:
+                       *pui32Field = pci_domain_nr(psPCIDev->bus);
+                       break;
+
+               case PVR_DRM_PCI_BUS:
+                       *pui32Field = psPCIDev->bus->number;
+                       break;
+
+               case PVR_DRM_PCI_DEV:
+                       *pui32Field = PCI_SLOT(psPCIDev->devfn);
+                       break;
+
+               case PVR_DRM_PCI_FUNC:
+                       *pui32Field = PCI_FUNC(psPCIDev->devfn);
+                       break;
+
+               default:
+                       return -EFAULT;
+       }
+
+       return 0;
+}
+DRI_DRM_STATIC IMG_INT
+PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+       IMG_UINT32 *pui32Args = (IMG_UINT32 *)arg;
+       IMG_UINT32 ui32Cmd = pui32Args[0];
+       IMG_UINT32 ui32Arg1 = pui32Args[1];
+       IMG_UINT32 *pui32OutArg = (IMG_UINT32 *)arg;
+       IMG_INT ret = 0;
+
+       mutex_lock(&gPVRSRVLock);
+
+       switch (ui32Cmd)
+       {
+               case PVR_DRM_UNPRIV_INIT_SUCCESFUL:
+                       *pui32OutArg = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
+                       break;
+
+               case PVR_DRM_UNPRIV_BUSID_TYPE:
+                       *pui32OutArg = PVR_DRM_BUS_TYPE_PCI;
+                       break;
+
+               case PVR_DRM_UNPRIV_BUSID_FIELD:
+                       ret = PVRDRMPCIBusIDField(dev, pui32OutArg, ui32Arg1);
+
+               default:
+                       ret = -EFAULT;
+       }
+
+       mutex_unlock(&gPVRSRVLock);
+
+       return ret;
+}
+
+#if 0
+struct drm_ioctl_desc sPVRDrmIoctls[] = {
+       DRM_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, 0),
+       DRM_IOCTL_DEF(PVR_DRM_IS_MASTER_IOCTL, PVRDRMIsMaster, DRM_MASTER),
+       DRM_IOCTL_DEF(PVR_DRM_UNPRIV_IOCTL, PVRDRMUnprivCmd, 0),
+#if defined(PDUMP)
+       DRM_IOCTL_DEF(PVR_DRM_DBGDRV_IOCTL, dbgdrv_ioctl, 0),
+#endif
+};
+
+static IMG_INT pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+
+static struct drm_driver sPVRDrmDriver = 
+{
+       .driver_features = 0,
+       .dev_priv_size = sizeof(sPVRDrmBuffer),
+       .load = PVRSRVDrmLoad,
+       .unload = PVRSRVDrmUnload,
+       .open = PVRSRVDrmOpen,
+       .postclose = PVRSRVDrmPostClose,
+       .suspend = PVRSRVDriverSuspend,
+       .resume = PVRSRVDriverResume,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = sPVRDrmIoctls,
+       .fops = 
+       {
+               .owner = THIS_MODULE,
+               .open = drm_open,
+               .release = drm_release,
+               .ioctl = drm_ioctl,
+               .mmap = PVRMMap,
+               .poll = drm_poll,
+               .fasync = drm_fasync,
+       },
+       .pci_driver = 
+       {
+               .name = PVR_DRM_NAME,
+               .id_table = asPciIdList,
+       },
+               
+       .name = PVR_DRM_NAME,
+       .desc = PVR_DRM_DESC,
+       .date = PVR_BUILD_DATE,
+       .major = PVRVERSION_MAJ,
+       .minor = PVRVERSION_MIN,
+       .patchlevel = PVRVERSION_BUILD,
+};
+
+static IMG_INT __init PVRSRVDrmInit(IMG_VOID)
+{
+       IMG_INT iRes;
+       sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+
+       
+       PVRDPFInit();
+
+       iRes = drm_init(&sPVRDrmDriver);
+
+       return iRes;
+}
+       
+static IMG_VOID __exit PVRSRVDrmExit(IMG_VOID)
+{
+       drm_exit(&sPVRDrmDriver);
+}
+
+module_init(PVRSRVDrmInit);
+module_exit(PVRSRVDrmExit);
+#endif 
+#endif 
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_drm.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux-intel/pvr_drm.h
new file mode 100644 (file)
index 0000000..fd8c81d
--- /dev/null
@@ -0,0 +1,80 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
+
+#include "pvr_drm_shared.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#define        PVR_DRM_MAKENAME_HELPER(x, y) x ## y
+#define        PVR_DRM_MAKENAME(x, y) PVR_DRM_MAKENAME_HELPER(x, y)
+
+IMG_INT PVRCore_Init(IMG_VOID);
+IMG_VOID PVRCore_Cleanup(IMG_VOID);
+IMG_INT PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
+IMG_INT PVRSRVRelease(struct drm_device *dev, struct drm_file *pFile);
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice);
+
+IMG_INT PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define        DRI_DRM_STATIC
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags);
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev);
+IMG_INT PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file);
+IMG_INT PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#else
+#define        DRI_DRM_STATIC  static
+#endif 
+
+#if defined(DISPLAY_CONTROLLER)
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
+extern void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device *);
+#endif
+
+#if defined(PDUMP)
+int dbgdrv_init(void);
+void dbgdrv_cleanup(void);
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+#define        PVR_DRM_SRVKM_IOCTL     _IO(0, PVR_DRM_SRVKM_CMD)
+#define        PVR_DRM_IS_MASTER_IOCTL _IO(0, PVR_DRM_IS_MASTER_CMD)
+#define        PVR_DRM_UNPRIV_IOCTL    _IO(0, PVR_DRM_UNPRIV_CMD)
+#define        PVR_DRM_DBGDRV_IOCTL    _IO(0, PVR_DRM_DBGDRV_CMD)
+#endif
+
+#endif
+
+#endif 
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/.gitignore b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/.gitignore
new file mode 100644 (file)
index 0000000..2f89523
--- /dev/null
@@ -0,0 +1,5 @@
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+*.o
+*.o.cmd
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/env_data.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/env_data.h
new file mode 100644 (file)
index 0000000..3d41219
--- /dev/null
@@ -0,0 +1,66 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+#define PVRSRV_MAX_BRIDGE_IN_SIZE      0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE     0x1000
+
+typedef        struct _PVR_PCI_DEV_TAG
+{
+       struct pci_dev          *psPCIDev;
+       HOST_PCI_INIT_FLAGS     ePCIFlags;
+       IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+typedef struct _ENV_DATA_TAG
+{
+       IMG_VOID                *pvBridgeData;
+       struct pm_dev           *psPowerDevice;
+       IMG_BOOL                bLISRInstalled;
+       IMG_BOOL                bMISRInstalled;
+       IMG_UINT32              ui32IRQ;
+       IMG_VOID                *pvISRCookie;
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+       struct workqueue_struct *psWorkQueue;
+#endif
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+       struct work_struct      sMISRWork;
+       IMG_VOID                *pvMISRData;
+#else
+       struct tasklet_struct   sMISRTasklet;
+#endif
+} ENV_DATA;
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/env_perproc.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/env_perproc.h
new file mode 100644 (file)
index 0000000..a6e49db
--- /dev/null
@@ -0,0 +1,56 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+
+#include "services.h"
+#include "handle.h"
+
+typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
+{
+       IMG_HANDLE hBlockAlloc;
+       struct proc_dir_entry *psProcDir;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       struct list_head sDRMAuthListHead;
+#endif
+} PVRSRV_ENV_PER_PROCESS_DATA;
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/event.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/event.c
new file mode 100644 (file)
index 0000000..3b8ab2f
--- /dev/null
@@ -0,0 +1,285 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <asm/system.h>
+#endif
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+#include "event.h"
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+   rwlock_t                       sLock;
+   struct list_head        sList;
+   
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+       atomic_t        sTimeStamp;
+       IMG_UINT32  ui32TimeStampPrevious;
+#if defined(DEBUG)
+       IMG_UINT        ui32Stats;
+#endif
+    wait_queue_head_t sWait;   
+       struct list_head        sList;
+       IMG_HANDLE                              hResItem;                               
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList;
+
+       if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), 
+               (IMG_VOID **)&psEventObjectList, IMG_NULL,
+               "Linux Event Object List") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));           
+               return PVRSRV_ERROR_OUT_OF_MEMORY;      
+       }
+
+       INIT_LIST_HEAD(&psEventObjectList->sList);
+
+       rwlock_init(&psEventObjectList->sLock);
+       
+       *phEventObjectList = (IMG_HANDLE *) psEventObjectList;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+       if(psEventObjectList)
+       {
+               IMG_BOOL bListEmpty;
+
+               read_lock(&psEventObjectList->sLock);
+               bListEmpty = list_empty(&psEventObjectList->sList);
+               read_unlock(&psEventObjectList->sLock);
+
+               if (!bListEmpty)
+               {
+                        PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+                        return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+               }
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEventObjectList, IMG_NULL);
+               
+       }
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
+{
+       if(hOSEventObjectList)
+       {
+               if(hOSEventObject)
+               {
+                       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject; 
+#if defined(DEBUG)
+                       PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif
+                       if(ResManFreeResByPtr(psLinuxEventObject->hResItem) != PVRSRV_OK)
+                       {
+                               return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+                       }
+                       
+                       return PVRSRV_OK;
+               }
+       }
+       return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+
+}
+
+static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+       unsigned long ulLockFlags;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags);
+       list_del(&psLinuxEventObject->sList);
+       write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags);
+
+#if defined(DEBUG)
+       PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif 
+
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
+       
+
+       return PVRSRV_OK;
+}
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject; 
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; 
+       IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+       PVRSRV_PER_PROCESS_DATA *psPerProc;
+       unsigned long ulLockFlags;
+
+       psPerProc = PVRSRVPerProcessData(ui32PID);
+       if (psPerProc == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       
+       if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), 
+               (IMG_VOID **)&psLinuxEventObject, IMG_NULL,
+               "Linux Event Object") != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));            
+               return PVRSRV_ERROR_OUT_OF_MEMORY;      
+       }
+       
+       INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+       atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+       psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+       psLinuxEventObject->ui32Stats = 0;
+#endif
+    init_waitqueue_head(&psLinuxEventObject->sWait);
+
+       psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+       psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                                                                        RESMAN_TYPE_EVENT_OBJECT,
+                                                                                                        psLinuxEventObject,
+                                                                                                        0,
+                                                                                                        &LinuxEventObjectDeleteCallback);      
+
+       write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags);
+       list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+       write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags);
+       
+       *phOSEventObject = psLinuxEventObject;
+
+       return PVRSRV_OK;        
+}
+
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+       PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; 
+       struct list_head *psListEntry, *psList;
+
+       psList = &psLinuxEventObjectList->sList;
+
+
+       read_lock(&psLinuxEventObjectList->sLock);
+       list_for_each(psListEntry, psList)
+       {               
+
+               psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);    
+               
+               atomic_inc(&psLinuxEventObject->sTimeStamp);    
+               wake_up_interruptible(&psLinuxEventObject->sWait);
+       }
+       read_unlock(&psLinuxEventObjectList->sLock);
+
+       return  PVRSRV_OK;
+       
+}
+
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+       IMG_UINT32 ui32TimeStamp;
+       DEFINE_WAIT(sWait);
+
+       PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+       IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+       
+       do      
+       {
+               prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+               ui32TimeStamp = (IMG_UINT32)atomic_read(&psLinuxEventObject->sTimeStamp);
+       
+               if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+               {
+                       break;
+               }
+
+               LinuxUnLockMutex(&gPVRSRVLock);         
+
+               ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+               
+               LinuxLockMutex(&gPVRSRVLock);
+#if defined(DEBUG)
+               psLinuxEventObject->ui32Stats++;
+#endif                 
+
+               
+       } while (ui32TimeOutJiffies);
+
+       finish_wait(&psLinuxEventObject->sWait, &sWait);        
+
+       psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+       return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/event.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/event.h
new file mode 100644 (file)
index 0000000..d07bc97
--- /dev/null
@@ -0,0 +1,32 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/linkage.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/linkage.h
new file mode 100644 (file)
index 0000000..7e6d09a
--- /dev/null
@@ -0,0 +1,52 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __LINKAGE_H__
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRI_DRM)
+long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+
+IMG_VOID PVRDPFInit(IMG_VOID);
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID);
+IMG_VOID PVROSFuncDeInit(IMG_VOID);
+
+#ifdef DEBUG
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el);
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
+
+#endif 
+
+#endif 
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/lock.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/lock.h
new file mode 100644 (file)
index 0000000..e0bf5ee
--- /dev/null
@@ -0,0 +1,32 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __LOCK_H__
+#define __LOCK_H__
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.c
new file mode 100644 (file)
index 0000000..68ebe67
--- /dev/null
@@ -0,0 +1,1971 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "syscommon.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       #include "lists.h"
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+typedef enum {
+    DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+    DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+    DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+    DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+    DEBUG_MEM_ALLOC_TYPE_IO,
+    DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+    DEBUG_MEM_ALLOC_TYPE_COUNT
+}DEBUG_MEM_ALLOC_TYPE;
+
+typedef struct _DEBUG_MEM_ALLOC_REC
+{
+    DEBUG_MEM_ALLOC_TYPE    eAllocType;
+       IMG_VOID                                *pvKey; 
+    IMG_VOID                *pvCpuVAddr;
+    IMG_UINT32              ulCpuPAddr;
+    IMG_VOID                *pvPrivateData;
+       IMG_UINT32                              ui32Bytes;
+       pid_t                                   pid;
+    IMG_CHAR                *pszFileName;
+    IMG_UINT32              ui32Line;
+    
+    struct _DEBUG_MEM_ALLOC_REC   *psNext;
+       struct _DEBUG_MEM_ALLOC_REC   **ppsThis;
+}DEBUG_MEM_ALLOC_REC;
+
+static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_MEM_ALLOC_REC)
+
+
+static DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
+
+static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+
+static IMG_UINT32 g_SysRAMWaterMark;
+static IMG_UINT32 g_SysRAMHighWaterMark;
+
+static IMG_UINT32 g_IOMemWaterMark;
+static IMG_UINT32 g_IOMemHighWaterMark;
+
+static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+                                       IMG_VOID *pvKey,
+                                       IMG_VOID *pvCpuVAddr,
+                                       IMG_UINT32 ulCpuPAddr,
+                                       IMG_VOID *pvPrivateData,
+                                       IMG_UINT32 ui32Bytes,
+                                       IMG_CHAR *pszFileName,
+                                       IMG_UINT32 ui32Line);
+
+static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
+
+
+static struct proc_dir_entry *g_SeqFileMemoryRecords =0;
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+typedef struct _DEBUG_LINUX_MEM_AREA_REC
+{
+       LinuxMemArea                *psLinuxMemArea;
+    IMG_UINT32                  ui32Flags;
+       pid_t                                       pid;
+
+       struct _DEBUG_LINUX_MEM_AREA_REC  *psNext;
+       struct _DEBUG_LINUX_MEM_AREA_REC  **ppsThis;
+}DEBUG_LINUX_MEM_AREA_REC;
+
+
+static IMPLEMENT_LIST_ANY_VA(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_LINUX_MEM_AREA_REC)
+
+
+
+
+static DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
+static IMG_UINT32 g_LinuxMemAreaCount;
+static IMG_UINT32 g_LinuxMemAreaWaterMark;
+static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
+
+
+static struct proc_dir_entry *g_SeqFileMemArea=0;
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemArea(struct seq_file *sfile, loff_t off);
+
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static PVRSRV_LINUX_MUTEX g_sDebugMutex;
+#endif
+
+#if (defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
+#endif
+
+static LinuxKMemCache *psLinuxMemAreaCache;
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+#endif
+
+static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID);
+static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea);
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags);
+static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea);
+static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
+#endif
+
+PVRSRV_ERROR
+LinuxMMInit(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       LinuxInitMutex(&g_sDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+               g_SeqFileMemArea = CreateProcReadEntrySeq(
+                                                                       "mem_areas", 
+                                                                       NULL, 
+                                                                       ProcSeqNextMemArea,
+                                                                       ProcSeqShowMemArea,
+                                                                       ProcSeqOff2ElementMemArea,
+                                                                       ProcSeqStartstopDebugMutex
+                                                                  );
+               if(!g_SeqFileMemArea)
+        {
+            return PVRSRV_ERROR_OUT_OF_MEMORY;
+        }
+    }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    {
+               g_SeqFileMemoryRecords =CreateProcReadEntrySeq(
+                                                                       "meminfo", 
+                                                                       NULL, 
+                                                                       ProcSeqNextMemoryRecords,
+                                                                       ProcSeqShowMemoryRecords, 
+                                                                       ProcSeqOff2ElementMemoryRecords,
+                                                                       ProcSeqStartstopDebugMutex
+                                                                  );
+        if(!g_SeqFileMemoryRecords)
+        {
+            return PVRSRV_ERROR_OUT_OF_MEMORY;
+        }
+    }
+#endif
+
+    psLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
+    if(!psLinuxMemAreaCache)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+    return PVRSRV_OK;
+}
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
+{
+       LinuxMemArea *psLinuxMemArea;
+
+       psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+       PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
+                               __FUNCTION__,
+                               psCurrentRecord->psLinuxMemArea,
+                               LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
+                               psCurrentRecord->psLinuxMemArea->ui32ByteSize));
+       
+       LinuxMemAreaDeepFree(psLinuxMemArea);
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+
+{
+       
+       PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+                                                       "type=%s "
+                                                       "CpuVAddr=%p "
+                                                       "CpuPAddr=0x%08x, "
+                                                       "allocated @ file=%s,line=%d",
+                       __FUNCTION__,
+                       DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
+                       psCurrentRecord->pvCpuVAddr,
+                       psCurrentRecord->ulCpuPAddr,
+                       psCurrentRecord->pszFileName,
+                       psCurrentRecord->ui32Line));
+       switch(psCurrentRecord->eAllocType)
+       {
+               case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+                       KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+                       break;
+               case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+                       IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+                       break;
+               case DEBUG_MEM_ALLOC_TYPE_IO:
+                       
+                       DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
+                       break;
+               case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
+                       VFreeWrapper(psCurrentRecord->pvCpuVAddr);
+                       break;
+               case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
+                       
+                       DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
+                       break;
+               case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
+                       KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
+                       break;
+               default:
+                       PVR_ASSERT(0);
+       }
+}
+#endif
+
+
+IMG_VOID
+LinuxMMCleanup(IMG_VOID)
+{
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+        if(g_LinuxMemAreaCount)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
+                    __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
+        }
+               
+               List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords,
+                                                                                       LinuxMMCleanup_MemAreas_ForEachCb);
+
+               RemoveProcEntrySeq( g_SeqFileMemArea );
+    }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    {
+        
+        
+               List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords,
+                                                                               LinuxMMCleanup_MemRecords_ForEachVa);
+
+               RemoveProcEntrySeq( g_SeqFileMemoryRecords );
+    }
+#endif
+
+    if(psLinuxMemAreaCache)
+    {
+        KMemCacheDestroyWrapper(psLinuxMemAreaCache); 
+        psLinuxMemAreaCache=NULL;
+    }
+}
+
+
+IMG_VOID *
+_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+    IMG_VOID *pvRet;
+    pvRet = kmalloc(ui32ByteSize, GFP_KERNEL);
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if(pvRet)
+    {
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+                               pvRet,
+                               pvRet,
+                               0,
+                               NULL,
+                               ui32ByteSize,
+                               pszFileName,
+                               ui32Line
+                               );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    return pvRet;
+}
+
+
+IMG_VOID
+_KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr, pszFileName,  ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    kfree(pvCpuVAddr);
+}
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID
+DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+                       IMG_VOID *pvKey,
+                       IMG_VOID *pvCpuVAddr,
+                       IMG_UINT32 ulCpuPAddr,
+                       IMG_VOID *pvPrivateData,
+                       IMG_UINT32 ui32Bytes,
+                       IMG_CHAR *pszFileName,
+                       IMG_UINT32 ui32Line)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+
+    LinuxLockMutex(&g_sDebugMutex);
+
+    psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
+
+    psRecord->eAllocType = eAllocType;
+    psRecord->pvKey = pvKey;
+    psRecord->pvCpuVAddr = pvCpuVAddr;
+    psRecord->ulCpuPAddr = ulCpuPAddr;
+    psRecord->pvPrivateData = pvPrivateData;
+    psRecord->pid = current->pid;
+    psRecord->ui32Bytes = ui32Bytes;
+    psRecord->pszFileName = pszFileName;
+    psRecord->ui32Line = ui32Line;
+    
+       List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
+    
+    g_WaterMarkData[eAllocType] += ui32Bytes;
+    if(g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+    {
+        g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
+    }
+
+    if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+    {
+        g_SysRAMWaterMark += ui32Bytes;
+        if(g_SysRAMWaterMark > g_SysRAMHighWaterMark)
+        {
+            g_SysRAMHighWaterMark = g_SysRAMWaterMark;
+        }
+    }
+    else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+            || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+    {
+        g_IOMemWaterMark += ui32Bytes;
+        if(g_IOMemWaterMark > g_IOMemHighWaterMark)
+        {
+            g_IOMemHighWaterMark = g_IOMemWaterMark;
+        }
+    }
+
+    LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va)
+{
+       DEBUG_MEM_ALLOC_TYPE eAllocType;
+       IMG_VOID *pvKey;
+       
+       eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
+       pvKey = va_arg(va, IMG_VOID*);
+
+       if(psCurrentRecord->eAllocType == eAllocType
+               && psCurrentRecord->pvKey == pvKey)
+       {
+               eAllocType = psCurrentRecord->eAllocType;
+               g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
+               
+               if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+                  || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+                  || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+                  || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+               {
+                       g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
+               }
+               else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+                               || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+               {
+                       g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
+               }
+               
+               List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
+               kfree(psCurrentRecord);
+
+               return IMG_TRUE;
+       }
+       else
+       {
+               return IMG_FALSE;
+       }
+}
+
+
+static IMG_VOID
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+    LinuxLockMutex(&g_sDebugMutex);
+
+    
+       if(!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
+                                                                                               DebugMemAllocRecordRemove_AnyVaCb,
+                                                                                               eAllocType,
+                                                                                               pvKey))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with pvKey=%p (called from %s, line %d\n",
+               __FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
+               pszFileName, ui32Line));
+       }
+
+    LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+static IMG_CHAR *
+DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
+{
+    IMG_CHAR *apszDebugMemoryRecordTypes[] = {
+        "KMALLOC",
+        "VMALLOC",
+        "ALLOC_PAGES",
+        "IOREMAP",
+        "IO",
+        "KMEM_CACHE_ALLOC"
+    };
+    return apszDebugMemoryRecordTypes[eAllocType];
+}
+#endif
+
+
+
+IMG_VOID *
+_VMallocWrapper(IMG_UINT32 ui32Bytes,
+                IMG_UINT32 ui32AllocFlags,
+                IMG_CHAR *pszFileName,
+                IMG_UINT32 ui32Line)
+{
+    pgprot_t PGProtFlags;
+    IMG_VOID *pvRet;
+    
+    switch(ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+            PGProtFlags = PAGE_KERNEL;
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+            PGProtFlags = PGPROT_WC(PAGE_KERNEL);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            PGProtFlags = PGPROT_UC(PAGE_KERNEL);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR,
+                     "VMAllocWrapper: unknown mapping flags=0x%08x",
+                     ui32AllocFlags));
+            dump_stack();
+            return NULL;
+    }
+
+       
+    pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+    
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if(pvRet)
+    {
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+                               pvRet,
+                               pvRet,
+                               0,
+                               NULL,
+                               PAGE_ALIGN(ui32Bytes),
+                               pszFileName,
+                               ui32Line
+                               );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    return pvRet;
+}
+
+
+IMG_VOID
+_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    vfree(pvCpuVAddr);
+}
+
+
+LinuxMemArea *
+NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    IMG_VOID *pvCpuVAddr;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        goto failed;
+    }
+
+    pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
+    if(!pvCpuVAddr)
+    {
+        goto failed;
+    }
+    
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+    
+    ReservePages(pvCpuVAddr, ui32Bytes);
+#endif
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
+    psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    
+    if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
+        OSInvalidateCPUCacheRangeKM(psLinuxMemArea, pvCpuVAddr, ui32Bytes);
+
+    return psLinuxMemArea;
+
+failed:
+    PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
+    if(psLinuxMemArea)
+        LinuxMemAreaStructFree(psLinuxMemArea);
+    return NULL;
+}
+
+
+IMG_VOID
+FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea);
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
+    PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+       UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
+                    psLinuxMemArea->ui32ByteSize);
+#endif
+
+    PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
+             __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
+    VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+IMG_VOID *
+_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+               IMG_UINT32 ui32Bytes,
+               IMG_UINT32 ui32MappingFlags,
+               IMG_CHAR *pszFileName,
+               IMG_UINT32 ui32Line)
+{
+    IMG_VOID *pvIORemapCookie;
+    
+    switch(ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+           pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+           pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags"));
+            return NULL;
+    }
+    
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if(pvIORemapCookie)
+    {
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+                               pvIORemapCookie,
+                               pvIORemapCookie,
+                               BasePAddr.uiAddr,
+                               NULL,
+                               ui32Bytes,
+                               pszFileName,
+                               ui32Line
+                               );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    return pvIORemapCookie;
+}
+
+
+IMG_VOID
+_IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP, pvIORemapCookie, pszFileName, ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    iounmap(pvIORemapCookie);
+}
+
+
+LinuxMemArea *
+NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+                       IMG_UINT32 ui32Bytes,
+                       IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    IMG_VOID *pvIORemapCookie;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
+    if(!pvIORemapCookie)
+    {
+        LinuxMemAreaStructFree(psLinuxMemArea);
+        return NULL;
+    }
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
+    psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
+    psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+    
+    IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static IMG_BOOL
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
+{
+       IMG_UINT32 ui32;
+       IMG_UINT32 ui32AddrChk;
+       IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+       
+       for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+               ui32 < ui32NumPages;
+               ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
+       {
+               if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
+               {
+                       break;
+               }
+       }
+       if (ui32 == ui32NumPages)
+       {
+               return IMG_FALSE;
+       }
+
+       if (!bPhysContig)
+       {
+               for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+                       ui32 < ui32NumPages;
+                       ui32++, ui32AddrChk += PAGE_SIZE)
+               {
+                       if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+                       {
+                               return IMG_FALSE;
+                       }
+               }
+       }
+
+       return IMG_TRUE;
+}
+#endif
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+    psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+    psLinuxMemArea->uData.sExternalKV.bPhysContig =
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+       (bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, ui32Bytes, bPhysContig))
+                                                    ? IMG_TRUE : IMG_FALSE;
+#else
+       bPhysContig;
+#endif
+    if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+    {
+       psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
+    }
+    else
+    {
+       psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
+    }
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+    
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+                  IMG_UINT32 ui32Bytes,
+                  IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
+    psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
+                           (IMG_VOID *)BasePAddr.uiAddr,
+                           0,
+                           BasePAddr.uiAddr,
+                           NULL,
+                           ui32Bytes,
+                           "unknown",
+                           0
+                           );
+#endif
+   
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
+    
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
+                              (IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
+#endif
+
+    
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    IMG_UINT32 ui32PageCount;
+    struct page **pvPageList;
+    IMG_HANDLE hBlockPageList;
+    IMG_INT32 i;               
+    PVRSRV_ERROR eError;
+    
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        goto failed_area_alloc;
+    }
+    
+    ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
+    eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount, (IMG_VOID **)&pvPageList, &hBlockPageList,
+                                                       "Array of pages");
+    if(eError != PVRSRV_OK)
+    {
+        goto failed_page_list_alloc;
+    }
+    
+    for(i=0; i<(IMG_INT32)ui32PageCount; i++)
+    {
+        pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+        if(!pvPageList[i])
+        {
+            goto failed_alloc_pages;
+        }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+       
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))               
+       SetPageReserved(pvPageList[i]);
+#else
+        mem_map_reserve(pvPageList[i]);
+#endif
+#endif
+
+    }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+                           pvPageList,
+                           0,
+                           0,
+                           NULL,
+                           PAGE_ALIGN(ui32Bytes),
+                           "unknown",
+                           0
+                           );
+#endif
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+    psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
+    psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+    
+    if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
+    {
+        psLinuxMemArea->bNeedsCacheInvalidate = IMG_TRUE;
+    }
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+    
+failed_alloc_pages:
+    for(i--; i >= 0; i--)
+    {
+        __free_pages(pvPageList[i], 0);
+    }
+    (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
+       psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL; 
+failed_page_list_alloc:
+    LinuxMemAreaStructFree(psLinuxMemArea);
+failed_area_alloc:
+    PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
+    
+    return NULL;
+}
+
+
+IMG_VOID
+FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    IMG_UINT32 ui32PageCount;
+    struct page **pvPageList;
+    IMG_HANDLE hBlockPageList;
+    IMG_INT32 i;
+
+    PVR_ASSERT(psLinuxMemArea);
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+    
+    ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+    pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
+    hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
+    
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, __FILE__, __LINE__);
+#endif
+
+    for(i=0;i<(IMG_INT32)ui32PageCount;i++)
+    {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))              
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))               
+        ClearPageReserved(pvPageList[i]);
+#else
+        mem_map_reserve(pvPageList[i]);
+#endif         
+#endif 
+        __free_pages(pvPageList[i], 0);
+    }
+
+    (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
+       psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL; 
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+struct page*
+LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
+                         IMG_UINT32 ui32ByteOffset)
+{
+    IMG_UINT32 ui32PageIndex;
+    IMG_CHAR *pui8Addr;
+
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+            return psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+        case LINUX_MEM_AREA_VMALLOC:
+            pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+            pui8Addr += ui32ByteOffset;
+            return vmalloc_to_page(pui8Addr);
+        case LINUX_MEM_AREA_SUB_ALLOC:
+             
+            return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+                                            psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+                                             + ui32ByteOffset);
+        default:
+            PVR_DPF((PVR_DBG_ERROR,
+                    "%s: Unsupported request for struct page from LinuxMemArea with type=%s",
+                    __FUNCTION__, LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
+            return NULL;
+    }
+}
+
+
+LinuxKMemCache *
+KMemCacheCreateWrapper(IMG_CHAR *pszName,
+                       size_t Size,
+                       size_t Align,
+                       IMG_UINT32 ui32Flags)
+{
+#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
+    ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
+#endif
+    return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+                               , NULL
+#endif 
+                           );
+}
+
+
+IMG_VOID
+KMemCacheDestroyWrapper(LinuxKMemCache *psCache)
+{
+    kmem_cache_destroy(psCache);
+}
+
+
+IMG_VOID *
+_KMemCacheAllocWrapper(LinuxKMemCache *psCache,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+                      gfp_t Flags,
+#else
+                      IMG_INT Flags,
+#endif
+                      IMG_CHAR *pszFileName,
+                      IMG_UINT32 ui32Line)
+{
+    IMG_VOID *pvRet;
+    
+    pvRet = kmem_cache_zalloc(psCache, Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+                           pvRet,
+                           pvRet,
+                           0,
+                           psCache,
+                           kmem_cache_size(psCache),
+                           pszFileName,
+                           ui32Line
+                           );
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    
+    return pvRet;
+}
+
+
+IMG_VOID
+_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    kmem_cache_free(psCache, pvObject);
+}
+
+
+const IMG_CHAR *
+KMemCacheNameWrapper(LinuxKMemCache *psCache)
+{
+    PVR_UNREFERENCED_PARAMETER(psCache);
+
+    
+    return "";
+}
+
+
+LinuxMemArea *
+NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+                   IMG_UINT32 ui32ByteOffset,
+                   IMG_UINT32 ui32Bytes)
+{
+    LinuxMemArea *psLinuxMemArea;
+    
+    PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
+    
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        return NULL;
+    }
+    
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+    psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea;
+    psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
+    psLinuxMemArea->bNeedsCacheInvalidate = psParentLinuxMemArea->bNeedsCacheInvalidate;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+    
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+        DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
+        psParentRecord = DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
+        DebugLinuxMemAreaRecordAdd(psLinuxMemArea, psParentRecord->ui32Flags);
+    }
+#endif
+    
+    return psLinuxMemArea;
+}
+
+
+static IMG_VOID
+FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+    
+    
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+static LinuxMemArea *
+LinuxMemAreaStructAlloc(IMG_VOID)
+{
+#if 0
+    LinuxMemArea *psLinuxMemArea;
+    psLinuxMemArea = kmem_cache_alloc(psLinuxMemAreaCache, GFP_KERNEL);
+    printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
+    dump_stack();
+    return psLinuxMemArea;
+#else
+    return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
+#endif
+}
+
+
+static IMG_VOID
+LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
+{
+    KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
+    
+    
+}
+
+
+IMG_VOID
+LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
+{
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_VMALLOC:
+            FreeVMallocLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            FreeAllocPagesLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_IOREMAP:
+            FreeIORemapLinuxMemArea(psLinuxMemArea);
+            break;
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+           FreeExternalKVLinuxMemArea(psLinuxMemArea);
+           break;
+        case LINUX_MEM_AREA_IO:
+            FreeIOLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_SUB_ALLOC:
+            FreeSubLinuxMemArea(psLinuxMemArea);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+            break;
+    }
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID
+DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
+    const IMG_CHAR *pi8FlagsString;
+    
+    LinuxLockMutex(&g_sDebugMutex);
+
+    if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
+        if(g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+        {
+            g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
+        }
+    }
+    g_LinuxMemAreaCount++;
+    
+    
+    psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
+    if(psNewRecord)
+    {
+        
+        psNewRecord->psLinuxMemArea = psLinuxMemArea;
+        psNewRecord->ui32Flags = ui32Flags;
+        psNewRecord->pid = current->pid;
+               
+               List_DEBUG_LINUX_MEM_AREA_REC_Insert(&g_LinuxMemAreaRecords, psNewRecord);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+                 "%s: failed to allocate linux memory area record.",
+                 __FUNCTION__));
+    }
+    
+    
+    pi8FlagsString = HAPFlagsToString(ui32Flags);
+    if(strstr(pi8FlagsString, "UNKNOWN"))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+                 "%s: Unexpected flags (0x%08x) associated with psLinuxMemArea @ %p",
+                 __FUNCTION__,
+                 ui32Flags,
+                 psLinuxMemArea));
+        
+    }
+
+    LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+
+static IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord,
+                                                                                  va_list va)
+{
+       LinuxMemArea *psLinuxMemArea;
+       
+       psLinuxMemArea = va_arg(va, LinuxMemArea*);
+       if(psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+       {
+               return psCurrentRecord;
+       }
+       else
+       {
+               return IMG_NULL;
+       }
+}
+
+
+static DEBUG_LINUX_MEM_AREA_REC *
+DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+    LinuxLockMutex(&g_sDebugMutex);
+       psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+                                                                                                               MatchLinuxMemArea_AnyVaCb,
+                                                                                                               psLinuxMemArea);
+       
+    LinuxUnLockMutex(&g_sDebugMutex);
+
+    return psCurrentRecord;
+}
+
+
+static IMG_VOID
+DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+    LinuxLockMutex(&g_sDebugMutex);
+
+    if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
+    }
+    g_LinuxMemAreaCount--;
+
+    
+       psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+                                                                                                               MatchLinuxMemArea_AnyVaCb,
+                                                                                                               psLinuxMemArea);
+       if(psCurrentRecord)
+       {
+               
+               List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
+               kfree(psCurrentRecord);
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for psLinuxMemArea=%p\n",
+                    __FUNCTION__, psLinuxMemArea));
+       }
+
+    LinuxUnLockMutex(&g_sDebugMutex);
+}
+#endif
+
+
+IMG_VOID *
+LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
+{
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_VMALLOC:
+            return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+        case LINUX_MEM_AREA_IOREMAP:
+            return psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+           return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
+        case LINUX_MEM_AREA_SUB_ALLOC:
+        {
+            IMG_CHAR *pAddr =
+                LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);  
+            if(!pAddr)
+            {
+                return NULL;
+            }
+            return pAddr + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+        }
+        default:
+            return NULL;
+    }
+}
+
+
+IMG_CPU_PHYADDR
+LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
+{
+    IMG_CPU_PHYADDR CpuPAddr;
+    
+    CpuPAddr.uiAddr = 0;
+
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+        {
+            CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
+            CpuPAddr.uiAddr += ui32ByteOffset;
+            break;
+        }
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+       {
+           if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+           {
+               CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr);
+               CpuPAddr.uiAddr += ui32ByteOffset;
+           }
+           else
+           {
+               IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+               IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex];
+
+               CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+                CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+           }
+            break;
+       }
+        case LINUX_MEM_AREA_IO:
+        {
+            CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
+            CpuPAddr.uiAddr += ui32ByteOffset;
+            break;
+        }
+        case LINUX_MEM_AREA_VMALLOC:
+        {
+            IMG_CHAR *pCpuVAddr;
+            pCpuVAddr =
+                (IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+            pCpuVAddr += ui32ByteOffset;
+            CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
+            break;
+        }
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+        {
+            struct page *page;
+            IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+            page = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+            CpuPAddr.uiAddr = page_to_phys(page);
+            CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+            break;
+        }
+        case LINUX_MEM_AREA_SUB_ALLOC:
+        {
+            CpuPAddr =
+                OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+                                      psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+                                        + ui32ByteOffset);
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+            PVR_ASSERT(CpuPAddr.uiAddr);
+           break;
+        }
+   }
+    
+    return CpuPAddr;
+}
+
+
+IMG_BOOL
+LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
+{
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+        case LINUX_MEM_AREA_IO:
+            return IMG_TRUE;
+
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+           return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+        case LINUX_MEM_AREA_VMALLOC:
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+           return IMG_FALSE;
+
+        case LINUX_MEM_AREA_SUB_ALLOC:
+             
+           return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+           break;
+    }
+    return IMG_FALSE;
+}
+
+
+const IMG_CHAR *
+LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+    
+    switch(eMemAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+            return "LINUX_MEM_AREA_IOREMAP";
+       case LINUX_MEM_AREA_EXTERNAL_KV:
+           return "LINUX_MEM_AREA_EXTERNAL_KV";
+        case LINUX_MEM_AREA_IO:
+            return "LINUX_MEM_AREA_IO";
+        case LINUX_MEM_AREA_VMALLOC:
+            return "LINUX_MEM_AREA_VMALLOC";
+        case LINUX_MEM_AREA_SUB_ALLOC:
+            return "LINUX_MEM_AREA_SUB_ALLOC";
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            return "LINUX_MEM_AREA_ALLOC_PAGES";
+        default:
+            PVR_ASSERT(0);
+    }
+
+    return "";
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start) 
+{
+       if(start) 
+       {
+           LinuxLockMutex(&g_sDebugMutex);             
+       }
+       else
+       {
+           LinuxUnLockMutex(&g_sDebugMutex);
+       }
+}
+#endif 
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+
+static IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_list va)
+{
+       off_t *pOff = va_arg(va, off_t*);
+       if (--(*pOff))
+       {
+               return IMG_NULL;
+       }
+       else
+       {
+               return psNode;
+       }
+}
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off) 
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord;
+       psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+                               List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+                                                                                                       DecOffMemAreaRec_AnyVaCb,
+                                                                                                       &off);
+       return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord;
+       if(!off) 
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+       psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+                               List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+                                                                                                       DecOffMemAreaRec_AnyVaCb,
+                                                                                                       &off);
+       return (void*)psRecord;
+}
+
+
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el; 
+       if(el == PVR_PROC_SEQ_START_TOKEN) 
+       {
+
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+        seq_printf( sfile,
+                                 "Number of Linux Memory Areas: %u\n"
+                          "At the current water mark these areas correspond to %u bytes (excluding SUB areas)\n"
+                          "At the highest water mark these areas corresponded to %u bytes (excluding SUB areas)\n"
+                          "\nDetails for all Linux Memory Areas:\n"
+                          "%s %-24s %s %s %-8s %-5s %s\n",
+                          g_LinuxMemAreaCount,
+                          g_LinuxMemAreaWaterMark,
+                          g_LinuxMemAreaHighWaterMark,
+                          "psLinuxMemArea",
+                          "LinuxMemType",
+                          "CpuVAddr",
+                          "CpuPAddr",
+                          "Bytes",
+                          "Pid",
+                          "Flags"
+                         );
+#else
+        seq_printf( sfile,
+                          "<mem_areas_header>\n"
+                          "\t<count>%u</count>\n"
+                          "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n" 
+                          "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n" 
+                          "</mem_areas_header>\n",
+                          g_LinuxMemAreaCount,
+                          g_LinuxMemAreaWaterMark,
+                          g_LinuxMemAreaHighWaterMark
+                         );
+#endif
+               return;
+       }
+
+        seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                       "%8p       %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
+#else
+                       "<linux_mem_area>\n"
+                       "\t<pointer>%8p</pointer>\n"
+                       "\t<type>%s</type>\n"
+                       "\t<cpu_virtual>%8p</cpu_virtual>\n"
+                       "\t<cpu_physical>%08x</cpu_physical>\n"
+                       "\t<bytes>%ld</bytes>\n"
+                       "\t<pid>%u</pid>\n"
+                       "\t<flags>%08lx</flags>\n"
+                       "\t<flags_string>%s</flags_string>\n"
+                       "</linux_mem_area>\n",
+#endif
+                       psRecord->psLinuxMemArea,
+                       LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
+                       LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+                       LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
+                       psRecord->psLinuxMemArea->ui32ByteSize,
+                       psRecord->pid,
+                       psRecord->ui32Flags,
+                       HAPFlagsToString(psRecord->ui32Flags)
+                      );
+
+}
+
+#endif 
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+
+static IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list va)
+{
+       off_t *pOff = va_arg(va, off_t*);
+       if (--(*pOff))
+       {
+               return IMG_NULL;
+       }
+       else
+       {
+               return psNode;
+       }
+}
+
+
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off) 
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+       psRecord = (DEBUG_MEM_ALLOC_REC*)
+               List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+                                                                               DecOffMemAllocRec_AnyVaCb,
+                                                                               &off);
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+       if(!psRecord) 
+       {
+               seq_printf( sfile, "</meminfo>\n");
+       }
+#endif
+
+       return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+       if(!off) 
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+       psRecord = (DEBUG_MEM_ALLOC_REC*)
+               List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+                                                                               DecOffMemAllocRec_AnyVaCb,
+                                                                               &off);
+
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+       if(!psRecord) 
+       {
+               seq_printf( sfile, "</meminfo>\n");
+       }
+#endif
+
+       return (void*)psRecord;
+}
+
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
+       if(el == PVR_PROC_SEQ_START_TOKEN) 
+       {
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+        
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via kmalloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via kmalloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via vmalloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via vmalloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via alloc_pages",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via alloc_pages",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via ioremap",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via ioremap",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes reserved for \"IO\" memory areas",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via kmem_cache_alloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        seq_printf( sfile, "\n");
+
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "The Current Water Mark for memory allocated from system RAM",
+                           g_SysRAMWaterMark);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "The Highest Water Mark for memory allocated from system RAM",
+                           g_SysRAMHighWaterMark);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "The Current Water Mark for memory allocated from IO memory",
+                           g_IOMemWaterMark);
+        seq_printf( sfile, "%-60s: %d bytes\n",
+                           "The Highest Water Mark for memory allocated from IO memory",
+                           g_IOMemHighWaterMark);
+
+        seq_printf( sfile, "\n");
+
+               seq_printf( sfile, "Details for all known allocations:\n"
+                           "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
+                           "Type",
+                           "CpuVAddr",
+                           "CpuPAddr",
+                           "Bytes",
+                           "PID",
+                           "PrivateData",
+                           "Filename:Line");
+
+#else 
+               
+               
+               seq_printf( sfile, "<meminfo>\n<meminfo_header>\n");
+               seq_printf( sfile,
+                           "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+               seq_printf( sfile,
+                           "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+               seq_printf( sfile,"\n" );
+
+               seq_printf( sfile,
+                           "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%d\"/>\n",
+                           g_SysRAMWaterMark);
+               seq_printf( sfile,
+                           "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%d\"/>\n",
+                           g_SysRAMHighWaterMark);
+               seq_printf( sfile,
+                           "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%d\"/>\n",
+                           g_IOMemWaterMark);
+               seq_printf( sfile,
+                           "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%d\"/>\n",
+                           g_IOMemHighWaterMark);
+
+               seq_printf( sfile, "</meminfo_header>\n");
+
+#endif 
+               return;
+       }
+
+    if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+    {
+               seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                           "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+#else
+                           "<allocation>\n"
+                           "\t<type>%s</type>\n"
+                           "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                           "\t<cpu_physical>%08x</cpu_physical>\n"
+                           "\t<bytes>%d</bytes>\n"
+                           "\t<pid>%d</pid>\n"
+                           "\t<private>%s</private>\n"
+                           "\t<filename>%s</filename>\n"
+                           "\t<line>%d</line>\n"
+                           "</allocation>\n",
+#endif
+                           DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+                           psRecord->pvCpuVAddr,
+                           psRecord->ulCpuPAddr,
+                           psRecord->ui32Bytes,
+                           psRecord->pid,
+                           "NULL",
+                           psRecord->pszFileName,
+                           psRecord->ui32Line);
+    }
+    else
+    {
+               seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                           "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+#else
+                           "<allocation>\n"
+                           "\t<type>%s</type>\n"
+                           "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                           "\t<cpu_physical>%08x</cpu_physical>\n"
+                           "\t<bytes>%d</bytes>\n"
+                           "\t<pid>%d</pid>\n"
+                           "\t<private>%s</private>\n"
+                           "\t<filename>%s</filename>\n"
+                           "\t<line>%d</line>\n"
+                           "</allocation>\n",
+#endif
+                           DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+                           psRecord->pvCpuVAddr,
+                           psRecord->ulCpuPAddr,
+                           psRecord->ui32Bytes,
+                           psRecord->pid,
+                           KMemCacheNameWrapper(psRecord->pvPrivateData),
+                           psRecord->pszFileName,
+                           psRecord->ui32Line);
+    }
+}
+
+#endif 
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+const IMG_CHAR *
+HAPFlagsToString(IMG_UINT32 ui32Flags)
+{
+    static IMG_CHAR szFlags[50];
+    IMG_INT32 i32Pos = 0;
+    IMG_UINT32 ui32CacheTypeIndex, ui32MapTypeIndex;
+    IMG_CHAR *apszCacheTypes[] = {
+        "UNCACHED",
+        "CACHED",
+        "WRITECOMBINE",
+        "UNKNOWN"
+    };
+    IMG_CHAR *apszMapType[] = {
+        "KERNEL_ONLY",
+        "SINGLE_PROCESS",
+        "MULTI_PROCESS",
+        "FROM_EXISTING_PROCESS",
+        "NO_CPU_VIRTUAL",
+        "UNKNOWN"
+    };
+    
+    
+    if(ui32Flags & PVRSRV_HAP_UNCACHED){
+        ui32CacheTypeIndex=0;
+    }else if(ui32Flags & PVRSRV_HAP_CACHED){
+        ui32CacheTypeIndex=1;
+    }else if(ui32Flags & PVRSRV_HAP_WRITECOMBINE){
+        ui32CacheTypeIndex=2;
+    }else{
+        ui32CacheTypeIndex=3;
+        PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
+                 __FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
+    }
+
+    
+    if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY){
+        ui32MapTypeIndex = 0;
+    }else if(ui32Flags & PVRSRV_HAP_SINGLE_PROCESS){
+        ui32MapTypeIndex = 1;
+    }else if(ui32Flags & PVRSRV_HAP_MULTI_PROCESS){
+        ui32MapTypeIndex = 2;
+    }else if(ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS){
+        ui32MapTypeIndex = 3;
+    }else if(ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL){
+        ui32MapTypeIndex = 4;
+    }else{
+        ui32MapTypeIndex = 5;
+        PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
+                 __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
+    }
+
+    i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
+    if (i32Pos <= 0)
+    {
+       PVR_DPF((PVR_DBG_ERROR, "%s: sprintf for cache type %u failed (%d)",
+               __FUNCTION__, ui32CacheTypeIndex, i32Pos));
+       szFlags[0] = 0;
+    }
+    else
+    {
+        sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);
+    }
+
+    return szFlags;
+}
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.h
new file mode 100644 (file)
index 0000000..4d37131
--- /dev/null
@@ -0,0 +1,328 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include <asm/io.h>
+
+#define        PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define        ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define        REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define        REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+#define        IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define        IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#define        VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page)
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define VM_INSERT_PAGE(vma, addr, page) remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, vma->vm_page_prot);
+#else
+#define VM_INSERT_PAGE(vma, addr, page) remap_page_range(vma, addr, page_to_phys(page), PAGE_SIZE, vma->vm_page_prot);
+#endif
+#endif
+
+static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr)
+{
+       return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
+               
+}
+
+typedef enum {
+    LINUX_MEM_AREA_IOREMAP,
+       LINUX_MEM_AREA_EXTERNAL_KV,
+    LINUX_MEM_AREA_IO,
+    LINUX_MEM_AREA_VMALLOC,
+    LINUX_MEM_AREA_ALLOC_PAGES,
+    LINUX_MEM_AREA_SUB_ALLOC,
+    LINUX_MEM_AREA_TYPE_COUNT
+}LINUX_MEM_AREA_TYPE;
+
+typedef struct _LinuxMemArea LinuxMemArea;
+
+
+struct _LinuxMemArea {
+    LINUX_MEM_AREA_TYPE eAreaType;
+    union _uData
+    {
+        struct _sIORemap
+        {
+            
+            IMG_CPU_PHYADDR CPUPhysAddr;
+            IMG_VOID *pvIORemapCookie;
+        }sIORemap;
+        struct _sExternalKV
+        {
+            
+           IMG_BOOL bPhysContig;
+           union {
+                   
+                   IMG_SYS_PHYADDR SysPhysAddr;
+                   IMG_SYS_PHYADDR *pSysPhysAddr;
+           } uPhysAddr;
+            IMG_VOID *pvExternalKV;
+        }sExternalKV;
+        struct _sIO
+        {
+            
+            IMG_CPU_PHYADDR CPUPhysAddr;
+        }sIO;
+        struct _sVmalloc
+        {
+            
+            IMG_VOID *pvVmallocAddress;
+        }sVmalloc;
+        struct _sPageList
+        {
+            
+            struct page **pvPageList;
+           IMG_HANDLE hBlockPageList;
+        }sPageList;
+        struct _sSubAlloc
+        {
+            
+            LinuxMemArea *psParentLinuxMemArea;
+            IMG_UINT32 ui32ByteOffset;
+        }sSubAlloc;
+    }uData;
+
+    IMG_UINT32 ui32ByteSize;           
+
+    IMG_UINT32 ui32AreaFlags;          
+
+    IMG_BOOL bMMapRegistered;          
+
+    IMG_BOOL bNeedsCacheInvalidate;
+
+    struct list_head   sMMapItem;
+
+    
+    struct list_head   sMMapOffsetStructList;
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+typedef kmem_cache_t LinuxKMemCache;
+#else
+typedef struct kmem_cache LinuxKMemCache;
+#endif
+
+
+PVRSRV_ERROR LinuxMMInit(IMG_VOID);
+
+
+IMG_VOID LinuxMMCleanup(IMG_VOID);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, __FILE__, __LINE__)
+#else
+#define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, NULL, 0)
+#endif
+IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+    _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
+#else
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+    _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
+#endif
+IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+                          IMG_UINT32 ui32Bytes,
+                          IMG_UINT32 ui32MappingFlags,
+                          IMG_CHAR *pszFileName,
+                          IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IOUnmapWrapper(pvIORemapCookie) \
+    _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
+#else
+#define IOUnmapWrapper(pvIORemapCookie) \
+    _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
+#endif
+IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
+
+
+IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
+#else
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, NULL, 0)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#else
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
+#else
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0)
+#endif
+IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
+
+
+LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+                                 IMG_UINT32 ui32ByteOffset,
+                                 IMG_UINT32 ui32Bytes);
+
+
+IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(LINUX_MEM_AREAS_DEBUG)
+IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
+#else
+#define LinuxMemAreaRegister(X)
+#endif
+
+
+IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+
+
+IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+#define         LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+
+static inline LinuxMemArea *
+LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
+{
+    if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+    }
+    else
+    {
+        return psLinuxMemArea;
+    }
+}
+
+
+static inline LINUX_MEM_AREA_TYPE
+LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
+{
+    return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+
+const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS)
+const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mmap.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mmap.c
new file mode 100644 (file)
index 0000000..5f1e982
--- /dev/null
@@ -0,0 +1,1128 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <linux/sched.h>
+#include <asm/current.h>
+#endif
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "proc.h"
+#include "mutex.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+static PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+static LinuxKMemCache *g_psMemmapCache = NULL;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static IMG_UINT32 g_ui32RegisteredAreas = 0;
+static IMG_UINT32 g_ui32TotalByteSize = 0;
+#endif
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static struct proc_dir_entry *g_ProcMMap;
+#endif 
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+#define MMAP2_PGOFF_RESOLUTION (32-PAGE_SHIFT+12)
+#define RESERVED_PGOFF_BITS 1
+#define        MAX_MMAP_HANDLE         ((1UL<<(MMAP2_PGOFF_RESOLUTION-RESERVED_PGOFF_BITS))-1)
+
+#define        FIRST_PHYSICAL_PFN      0
+#define        LAST_PHYSICAL_PFN       (FIRST_PHYSICAL_PFN + MAX_MMAP_HANDLE)
+#define        FIRST_SPECIAL_PFN       (LAST_PHYSICAL_PFN + 1)
+#define        LAST_SPECIAL_PFN        (FIRST_SPECIAL_PFN + MAX_MMAP_HANDLE)
+
+#else  
+
+#if PAGE_SHIFT != 12
+#error This build variant has not yet been made non-4KB page-size aware
+#endif
+
+#if defined(PVR_MMAP_OFFSET_BASE)
+#define        FIRST_SPECIAL_PFN       PVR_MMAP_OFFSET_BASE
+#else
+#define        FIRST_SPECIAL_PFN       0x80000000UL
+#endif
+
+#if defined(PVR_NUM_MMAP_HANDLES)
+#define        MAX_MMAP_HANDLE         PVR_NUM_MMAP_HANDLES
+#else
+#define        MAX_MMAP_HANDLE         0x7fffffffUL
+#endif
+
+#endif 
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_BOOL
+PFNIsPhysical(IMG_UINT32 pfn)
+{
+       
+       return ( (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_BOOL
+PFNIsSpecial(IMG_UINT32 pfn)
+{
+       
+       return ((pfn >= FIRST_SPECIAL_PFN) ) ? IMG_TRUE : IMG_FALSE;
+}
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_HANDLE
+MMapOffsetToHandle(IMG_UINT32 pfn)
+{
+       if (PFNIsPhysical(pfn))
+       {
+               PVR_ASSERT(PFNIsPhysical(pfn));
+               return IMG_NULL;
+       }
+       return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
+}
+#endif
+
+static inline IMG_UINT32
+HandleToMMapOffset(IMG_HANDLE hHandle)
+{
+       IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+       if (PFNIsSpecial(ulHandle))
+       {
+               PVR_ASSERT(PFNIsSpecial(ulHandle));
+               return 0;
+       }
+#endif
+       return ulHandle + FIRST_SPECIAL_PFN;
+}
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_BOOL
+LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
+{
+    return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_UINT32
+GetCurrentThreadID(IMG_VOID)
+{
+       
+       return (IMG_UINT32)current->pid;
+}
+#endif
+
+static PKV_OFFSET_STRUCT
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8x)",
+             __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+    psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
+    if(psOffsetStruct == IMG_NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+        return IMG_NULL;
+    }
+    
+    psOffsetStruct->ui32MMapOffset = ui32Offset;
+
+    psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+    psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+
+    
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    psOffsetStruct->ui32TID = GetCurrentThreadID();
+#endif
+    psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    
+    psOffsetStruct->pszName = pszName;
+#endif
+
+    list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
+
+    return psOffsetStruct;
+}
+
+
+static IMG_VOID
+DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+#ifdef DEBUG
+    IMG_CPU_PHYADDR CpuPAddr;
+    CpuPAddr = LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0);
+#endif
+
+    list_del(&psOffsetStruct->sAreaItem);
+
+    if (psOffsetStruct->bOnMMapList)
+    {
+        list_del(&psOffsetStruct->sMMapItem);
+    }
+
+#ifdef DEBUG
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+             "psLinuxMemArea=%p, CpuPAddr=0x%08X", __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             CpuPAddr.uiAddr));
+#endif
+    
+    KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
+}
+
+
+static inline IMG_VOID
+DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
+                               IMG_UINT32 *pui32RealByteSize,
+                               IMG_UINT32 *pui32ByteOffset)
+{
+    IMG_UINT32 ui32PageAlignmentOffset;
+    IMG_CPU_PHYADDR CpuPAddr;
+    
+    CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+    ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+    
+    *pui32ByteOffset = ui32PageAlignmentOffset;
+
+    *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+
+PVRSRV_ERROR
+PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                               IMG_HANDLE hMHandle,
+                                IMG_UINT32 *pui32MMapOffset,
+                                IMG_UINT32 *pui32ByteOffset,
+                                IMG_UINT32 *pui32RealByteSize,
+                               IMG_UINT32 *pui32UserVAddr)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_HANDLE hOSMemHandle;
+    PVRSRV_ERROR eError;
+
+    LinuxLockMutex(&g_sMMapMutex);
+
+    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+    if (eError != PVRSRV_OK)
+    {
+       PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
+
+       goto exit_unlock;
+    }
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+                                   pui32RealByteSize,
+                                   pui32ByteOffset);
+
+    
+    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+        if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
+        {
+
+          PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+          
+          *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+          *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+          psOffsetStruct->ui32RefCount++;
+
+          eError = PVRSRV_OK;
+          goto exit_unlock;
+        }
+    }
+
+    
+    *pui32UserVAddr = 0;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
+    {
+        *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+        PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+    }
+    else
+#endif
+    {
+        *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+        PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+#endif
+    }
+
+    psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
+    if (psOffsetStruct == IMG_NULL)
+    {
+        eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+       goto exit_unlock;
+    }
+
+    
+    list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+
+    psOffsetStruct->bOnMMapList = IMG_TRUE;
+
+    psOffsetStruct->ui32RefCount++;
+
+    eError = PVRSRV_OK;
+
+       
+
+
+       *pui32MMapOffset = *pui32MMapOffset << (PAGE_SHIFT - 12);
+
+exit_unlock:
+    LinuxUnLockMutex(&g_sMMapMutex);
+
+    return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                               IMG_HANDLE hMHandle,
+                               IMG_BOOL *pbMUnmap,
+                               IMG_UINT32 *pui32RealByteSize,
+                                IMG_UINT32 *pui32UserVAddr)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_HANDLE hOSMemHandle;
+    PVRSRV_ERROR eError;
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    LinuxLockMutex(&g_sMMapMutex);
+
+    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+    if (eError != PVRSRV_OK)
+    {
+       PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
+
+       goto exit_unlock;
+    }
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    
+    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+        if (psOffsetStruct->ui32PID == ui32PID)
+        {
+           if (psOffsetStruct->ui32RefCount == 0)
+           {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area %p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
+               eError = PVRSRV_ERROR_STILL_MAPPED;
+               goto exit_unlock;
+           }
+
+           psOffsetStruct->ui32RefCount--;
+
+           *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
+
+           *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
+           *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+
+           eError = PVRSRV_OK;
+           goto exit_unlock;
+        }
+    }
+
+    
+    PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %p (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+
+    eError =  PVRSRV_ERROR_MAPPING_NOT_FOUND;
+
+exit_unlock:
+    LinuxUnLockMutex(&g_sMMapMutex);
+
+    return eError;
+}
+
+static inline PKV_OFFSET_STRUCT
+FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    IMG_UINT32 ui32TID = GetCurrentThreadID();
+#endif
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+    {
+        if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
+        {
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+           
+           if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
+#endif
+           {
+               return psOffsetStruct;
+           }
+        }
+    }
+
+    return IMG_NULL;
+}
+
+
+static IMG_BOOL
+DoMapToUser(LinuxMemArea *psLinuxMemArea,
+            struct vm_area_struct* ps_vma,
+            IMG_UINT32 ui32ByteOffset)
+{
+    IMG_UINT32 ui32ByteSize;
+
+    if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),            
+                    ps_vma,
+                    psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
+    }
+
+    
+    ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+    PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+#if defined (__sparc__)
+    
+#error "SPARC not supported"
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    if (PFNIsPhysical(ps_vma->vm_pgoff))
+    {
+       IMG_INT result;
+
+       PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+       PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
+        
+       result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
+
+        if(result == 0)
+        {
+            return IMG_TRUE;
+        }
+
+        PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
+    }
+#endif
+
+    {
+        
+        IMG_UINT32 ulVMAPos;
+       IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+       IMG_UINT32 ui32PA;
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+       IMG_BOOL bMixedMap = IMG_FALSE;
+#endif
+       
+       for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+       {
+           IMG_UINT32 pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+           if (!pfn_valid(pfn))
+           {
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+                PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn));
+                return IMG_FALSE;
+#else
+               bMixedMap = IMG_TRUE;
+#endif
+           }
+       }
+
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+       if (bMixedMap)
+       {
+            ps_vma->vm_flags |= VM_MIXEDMAP;
+       }
+#endif
+       
+        ulVMAPos = ps_vma->vm_start;
+       for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+       {
+           IMG_UINT32 pfn;
+           IMG_INT result;
+
+           pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+           if (bMixedMap)
+           {
+               result = vm_insert_mixed(ps_vma, ulVMAPos, pfn);
+                if(result != 0)
+                {
+                    PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result));
+                    return IMG_FALSE;
+                }
+           }
+           else
+#endif
+           {
+               struct page *psPage;
+
+               PVR_ASSERT(pfn_valid(pfn));
+
+               psPage = pfn_to_page(pfn);
+
+               result = VM_INSERT_PAGE(ps_vma,  ulVMAPos, psPage);
+                if(result != 0)
+                {
+                    PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
+                    return IMG_FALSE;
+                }
+           }
+            ulVMAPos += PAGE_SIZE;
+        }
+    }
+
+    return IMG_TRUE;
+}
+
+
+static IMG_VOID
+MMapVOpenNoLock(struct vm_area_struct* ps_vma)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+    PVR_ASSERT(psOffsetStruct != IMG_NULL)
+    psOffsetStruct->ui32Mapped++;
+    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+    if (psOffsetStruct->ui32Mapped > 1)
+    {
+       PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %u)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
+        PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+    }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %d, ui32Mapped %d",
+             __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+             psOffsetStruct->ui32MMapOffset,
+             psOffsetStruct->ui32Mapped));
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+    MOD_INC_USE_COUNT;
+#endif
+}
+
+
+static void
+MMapVOpen(struct vm_area_struct* ps_vma)
+{
+    LinuxLockMutex(&g_sMMapMutex);
+
+    MMapVOpenNoLock(ps_vma);
+
+    LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+static IMG_VOID
+MMapVCloseNoLock(struct vm_area_struct* ps_vma)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+    PVR_ASSERT(psOffsetStruct != IMG_NULL)
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s: psLinuxMemArea %p, CpuVAddr %p ui32MMapOffset %d, ui32Mapped %d",
+             __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+             psOffsetStruct->ui32MMapOffset,
+             psOffsetStruct->ui32Mapped));
+#endif
+
+    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+    psOffsetStruct->ui32Mapped--;
+    if (psOffsetStruct->ui32Mapped == 0)
+    {
+       if (psOffsetStruct->ui32RefCount != 0)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct %p has non-zero reference count (ui32RefCount = %u). User mode address of start of mapping: 0x%x", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
+       }
+
+       DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    ps_vma->vm_private_data = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+    MOD_DEC_USE_COUNT;
+#endif
+}
+
+static void
+MMapVClose(struct vm_area_struct* ps_vma)
+{
+    LinuxLockMutex(&g_sMMapMutex);
+
+    MMapVCloseNoLock(ps_vma);
+
+    LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+static struct vm_operations_struct MMapIOOps =
+{
+       .open=MMapVOpen,
+       .close=MMapVClose
+};
+
+
+int
+PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+    IMG_UINT32 ui32ByteSize;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    int iRetVal = 0;
+
+    PVR_UNREFERENCED_PARAMETER(pFile);
+
+    LinuxLockMutex(&g_sMMapMutex);
+    
+    ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+    
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
+                              " and ui32ByteSize %d(0x%08x)",
+            __FUNCTION__,
+            ps_vma->vm_pgoff,
+            ui32ByteSize, ui32ByteSize));
+   
+    psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+    if (psOffsetStruct == IMG_NULL)
+    {
+#if defined(SUPPORT_DRI_DRM)
+        LinuxUnLockMutex(&g_sMMapMutex);
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+       
+        return drm_mmap(pFile, ps_vma);
+#else
+       
+       return -ENOENT;
+#endif
+#else
+        PVR_UNREFERENCED_PARAMETER(pFile);
+
+        PVR_DPF((PVR_DBG_ERROR,
+             "%s: Attempted to mmap unregistered area at vm_pgoff 0x%lx",
+             __FUNCTION__, ps_vma->vm_pgoff));
+        iRetVal = -EINVAL;
+#endif
+        goto unlock_and_return;
+    }
+    list_del(&psOffsetStruct->sMMapItem);
+    psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+    
+    if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+        ((ps_vma->vm_flags & VM_SHARED) == 0))
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
+        iRetVal = -EINVAL;
+        goto unlock_and_return;
+    }
+   
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+         __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+
+    ps_vma->vm_flags |= VM_RESERVED;
+    ps_vma->vm_flags |= VM_IO;
+
+    
+    ps_vma->vm_flags |= VM_DONTEXPAND;
+    
+    
+    ps_vma->vm_flags |= VM_DONTCOPY;
+
+    ps_vma->vm_private_data = (void *)psOffsetStruct;
+    
+    switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+            
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+           ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
+           iRetVal = -EINVAL;
+           goto unlock_and_return;
+    }
+    
+    
+    ps_vma->vm_ops = &MMapIOOps;
+    
+    if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+    {
+        iRetVal = -EAGAIN;
+        goto unlock_and_return;
+    }
+    
+    PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
+
+    psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+
+    
+    if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate)
+    {
+        IMG_UINT32 ui32RealByteSize, ui32ByteOffset;
+        IMG_VOID *pvBase;
+
+        DetermineUsersSizeAndByteOffset(psOffsetStruct->psLinuxMemArea,
+                                        &ui32RealByteSize,
+                                        &ui32ByteOffset);
+
+        ui32RealByteSize = psOffsetStruct->psLinuxMemArea->ui32ByteSize;
+        pvBase = (IMG_VOID *)ps_vma->vm_start + ui32ByteOffset;
+
+        OSInvalidateCPUCacheRangeKM(psOffsetStruct->psLinuxMemArea,
+                                    pvBase, ui32RealByteSize);
+        psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate = IMG_FALSE;
+    }
+
+    
+    MMapVOpenNoLock(ps_vma);
+    
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+             __FUNCTION__, ps_vma->vm_pgoff));
+    
+unlock_and_return:
+    if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
+    {
+       DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    LinuxUnLockMutex(&g_sMMapMutex);
+    
+    return iRetVal;
+}
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start) 
+{
+       if(start) 
+       {
+           LinuxLockMutex(&g_sMMapMutex);              
+       }
+       else
+       {
+           LinuxUnLockMutex(&g_sMMapMutex);
+       }
+}
+
+
+static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
+{
+    LinuxMemArea *psLinuxMemArea;
+       if(!off) 
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+    list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
+    {
+        PKV_OFFSET_STRUCT psOffsetStruct;
+
+               list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+        {
+               off--;
+               if (off == 0)
+               {                               
+                               PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+                               return (void*)psOffsetStruct;
+                   }
+        }
+    }
+       return (void*)0;
+}
+
+static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
+{
+       return ProcSeqOff2ElementMMapRegistrations(sfile,off);
+}
+
+
+static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
+{
+       KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
+    LinuxMemArea *psLinuxMemArea;
+       IMG_UINT32 ui32RealByteSize;
+       IMG_UINT32 ui32ByteOffset;
+
+       if(el == PVR_PROC_SEQ_START_TOKEN) 
+       {
+        seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                                                 "Allocations registered for mmap: %u\n"
+                          "In total these areas correspond to %u bytes\n"
+                          "psLinuxMemArea "
+                                                 "UserVAddr "
+                                                 "KernelVAddr "
+                                                 "CpuPAddr "
+                          "MMapOffset "
+                          "ByteLength "
+                          "LinuxMemType             "
+                                                 "Pid   Name     Flags\n",
+#else
+                          "<mmap_header>\n"
+                          "\t<count>%u</count>\n"
+                          "\t<bytes>%u</bytes>\n"
+                          "</mmap_header>\n",
+#endif
+                                                 g_ui32RegisteredAreas,
+                          g_ui32TotalByteSize
+                          );
+               return;
+       }
+
+       psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+
+       DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+                                                                       &ui32RealByteSize,
+                                                                       &ui32ByteOffset);
+
+       seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                                               "%-8p       %08x %-8p %08x %08x   %-8d   %-24s %-5u %-8s %08x(%s)\n",
+#else
+                        "<mmap_record>\n"
+                                               "\t<pointer>%-8p</pointer>\n"
+                        "\t<user_virtual>%-8x</user_virtual>\n"
+                        "\t<kernel_virtual>%-8p</kernel_virtual>\n"
+                        "\t<cpu_physical>%08x</cpu_physical>\n"
+                        "\t<mmap_offset>%08x</mmap_offset>\n"
+                        "\t<bytes>%-8d</bytes>\n"
+                        "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+                        "\t<pid>%-5u</pid>\n"
+                        "\t<name>%-8s</name>\n"
+                        "\t<flags>%08x</flags>\n"
+                        "\t<flags_string>%s</flags_string>\n"
+                        "</mmap_record>\n",
+#endif
+                        psLinuxMemArea,
+                                               psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+                                               LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+                        LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
+                                               psOffsetStruct->ui32MMapOffset,
+                                               psLinuxMemArea->ui32ByteSize,
+                        LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+                                               psOffsetStruct->ui32PID,
+                                               psOffsetStruct->pszName,
+                                               psLinuxMemArea->ui32AreaFlags,
+                        HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+}
+
+#endif
+
+
+PVRSRV_ERROR
+PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVRSRV_ERROR eError;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+    LinuxLockMutex(&g_sMMapMutex);
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8x)",
+             __FUNCTION__, pszName, psLinuxMemArea,  psLinuxMemArea->ui32AreaFlags));
+#endif
+
+    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+    
+    if(psLinuxMemArea->bMMapRegistered)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
+                __FUNCTION__, psLinuxMemArea));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+       goto exit_unlock;
+    }
+
+    list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+    psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    g_ui32RegisteredAreas++;
+    
+    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
+    }
+#endif
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    LinuxUnLockMutex(&g_sMMapMutex);
+
+    return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVRSRV_ERROR eError;
+    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+
+    LinuxLockMutex(&g_sMMapMutex);
+
+    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+       if (psOffsetStruct->ui32Mapped != 0)
+       {
+            PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %u",  __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+               eError = PVRSRV_ERROR_STILL_MAPPED;
+               goto exit_unlock;
+       }
+       else
+       {
+             
+            PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped",  __FUNCTION__, psOffsetStruct));
+       }
+
+       PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
+
+       DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    list_del(&psLinuxMemArea->sMMapItem);
+
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    g_ui32RegisteredAreas--;
+    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
+    }
+#endif
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    LinuxUnLockMutex(&g_sMMapMutex);
+    return eError;
+}
+
+
+PVRSRV_ERROR
+LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+    return PVRSRV_OK;
+}
+
+IMG_VOID
+LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+    IMG_BOOL bWarn = IMG_FALSE;
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+    LinuxLockMutex(&g_sMMapMutex);
+
+    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+    {
+       if (psOffsetStruct->ui32PID == ui32PID)
+       {
+           if (!bWarn)
+           {
+               PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
+               bWarn = IMG_TRUE;
+           }
+           PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+           PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+           DestroyOffsetStruct(psOffsetStruct);
+       }
+    }
+
+    LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+    PVRSRV_ERROR eError;
+
+    eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+    if (eError != PVRSRV_OK)
+    {
+       PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
+       return eError;
+    }
+
+    return eError;
+}
+
+
+IMG_VOID
+PVRMMapInit(IMG_VOID)
+{
+    LinuxInitMutex(&g_sMMapMutex);
+
+    g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
+    if (!g_psMemmapCache)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+       goto error;
+    }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+       g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL, 
+                                                 ProcSeqNextMMapRegistrations,
+                                                 ProcSeqShowMMapRegistrations,
+                                                 ProcSeqOff2ElementMMapRegistrations,
+                                                 ProcSeqStartstopMMapRegistations
+                                                );
+#endif  
+    return;
+
+error:
+    PVRMMapCleanup();
+    return;
+}
+
+
+IMG_VOID
+PVRMMapCleanup(IMG_VOID)
+{
+    PVRSRV_ERROR eError;
+
+    if (!list_empty(&g_sMMapAreaList))
+    {
+       LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+       PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
+       
+       PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
+       list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
+       {
+               eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
+               }
+               PVR_ASSERT(eError == PVRSRV_OK);
+
+               LinuxMemAreaDeepFree(psLinuxMemArea);
+       }
+    }
+    PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    RemoveProcEntrySeq(g_ProcMMap);
+#endif 
+
+    if(g_psMemmapCache)
+    {
+        KMemCacheDestroyWrapper(g_psMemmapCache);
+        g_psMemmapCache = NULL;
+    }
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mmap.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mmap.h
new file mode 100644 (file)
index 0000000..486154a
--- /dev/null
@@ -0,0 +1,113 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#if defined(VM_MIXEDMAP)
+#define        PVR_MAKE_ALL_PFNS_SPECIAL
+#endif
+
+#include "perproc.h"
+#include "mm.h"
+
+typedef struct KV_OFFSET_STRUCT_TAG
+{
+    
+    IMG_UINT32                 ui32Mapped;
+
+    
+    IMG_UINT32                  ui32MMapOffset;
+    
+    IMG_UINT32                 ui32RealByteSize;
+
+    
+    LinuxMemArea                *psLinuxMemArea;
+    
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    
+    IMG_UINT32                 ui32TID;
+#endif
+
+    
+    IMG_UINT32                 ui32PID;
+
+    
+    IMG_BOOL                   bOnMMapList;
+
+    
+    IMG_UINT32                 ui32RefCount;
+
+    
+    IMG_UINT32                 ui32UserVAddr;
+
+    
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR             *pszName;
+#endif
+    
+   
+   struct list_head            sMMapItem;
+
+   
+   struct list_head            sAreaItem;
+}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+
+
+IMG_VOID PVRMMapInit(IMG_VOID);
+
+
+IMG_VOID PVRMMapCleanup(IMG_VOID);
+
+
+PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                            IMG_HANDLE hMHandle,
+                                             IMG_UINT32 *pui32MMapOffset,
+                                             IMG_UINT32 *pui32ByteOffset,
+                                             IMG_UINT32 *pui32RealByteSize,                                                 IMG_UINT32 *pui32UserVAddr);
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                               IMG_HANDLE hMHandle,
+                               IMG_BOOL *pbMUnmap,
+                               IMG_UINT32 *pui32RealByteSize,
+                                IMG_UINT32 *pui32UserVAddr);
+
+int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/module.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/module.c
new file mode 100644 (file)
index 0000000..4613496
--- /dev/null
@@ -0,0 +1,741 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(SUPPORT_DRI_DRM)
+       
+       #if defined(LDM_PLATFORM)
+               #define PVR_LDM_PLATFORM_MODULE
+               #define PVR_LDM_MODULE
+       #else
+               #if defined(LDM_PCI)
+                       #define PVR_LDM_PCI_MODULE
+                       #define PVR_LDM_MODULE
+               #endif
+       #endif
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#include <linux/platform_device.h>
+#endif 
+
+#if defined(PVR_LDM_PCI_MODULE)
+#include <linux/pci.h>
+#endif 
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+#include <asm/uaccess.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "private_data.h"
+#include "lock.h"
+#include "linkage.h"
+#include "pvr_debugfs.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+#define DRVNAME                PVRSRV_MODNAME
+#define DEVNAME                PVRSRV_MODNAME
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+#include <linux/moduleparam.h>
+extern IMG_UINT32 gPVRDebugLevel;
+module_param(gPVRDebugLevel, uint, 0644);
+MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
+#endif 
+
+#if defined(PVR_LDM_MODULE)
+static struct class *psPvrClass;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+static int AssignedMajorNumber;
+
+static int PVRSRVOpen(struct inode* pInode, struct file* pFile);
+static int PVRSRVRelease(struct inode* pInode, struct file* pFile);
+
+static struct file_operations pvrsrv_fops =
+{
+       .owner=THIS_MODULE,
+       .unlocked_ioctl = PVRSRV_BridgeDispatchKM,
+       .open=PVRSRVOpen,
+       .release=PVRSRVRelease,
+       .mmap=PVRMMap,
+};
+#endif 
+
+PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+IMG_UINT32 gui32ReleasePID;
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+static IMG_UINT32 gPVRPowerLevel;
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#define        LDM_DEV struct platform_device
+#define        LDM_DRV struct platform_driver
+#endif 
+
+#if defined(PVR_LDM_PCI_MODULE)
+#define        LDM_DEV struct pci_dev
+#define        LDM_DRV struct pci_driver
+#endif 
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverRemove(LDM_DEV *device);
+static int PVRSRVDriverProbe(LDM_DEV *device);
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static void PVRSRVDriverRemove(LDM_DEV *device);
+static int PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
+#endif
+static int PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state);
+static void PVRSRVDriverShutdown(LDM_DEV *device);
+static int PVRSRVDriverResume(LDM_DEV *device);
+
+#if defined(PVR_LDM_PCI_MODULE)
+struct pci_device_id powervr_id_table[] __devinitdata = {
+       { PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID) },
+#if defined (SYS_SGX_DEV1_DEVICE_ID)
+       { PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID) },
+#endif
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, powervr_id_table);
+#endif
+
+static LDM_DRV powervr_driver = {
+#if defined(PVR_LDM_PLATFORM_MODULE)
+       .driver = {
+               .name           = DRVNAME,
+       },
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+       .name           = DRVNAME,
+       .id_table = powervr_id_table,
+#endif
+       .probe          = PVRSRVDriverProbe,
+#if defined(PVR_LDM_PLATFORM_MODULE)
+       .remove         = PVRSRVDriverRemove,
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+       .remove         = __devexit_p(PVRSRVDriverRemove),
+#endif
+       .suspend        = PVRSRVDriverSuspend,
+       .resume         = PVRSRVDriverResume,
+       .shutdown       = PVRSRVDriverShutdown,
+};
+
+LDM_DEV *gpsPVRLDMDev;
+
+#if defined(MODULE) && defined(PVR_LDM_PLATFORM_MODULE)
+
+static IMG_VOID PVRSRVDeviceRelease(struct device unref__ *pDevice)
+{
+}
+
+static struct platform_device powervr_device = {
+       .name                   = DEVNAME,
+       .id                             = -1,
+       .dev                    = {
+               .release        = PVRSRVDeviceRelease
+       }
+};
+
+#endif 
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverProbe(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *id)
+#endif
+{
+       SYS_DATA *psSysData;
+
+       PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
+
+#if 0
+       
+       if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+       {
+               return -EINVAL;
+       }
+#endif 
+       
+       psSysData = SysAcquireDataNoCheck();
+       if ( psSysData == IMG_NULL)
+       {
+               gpsPVRLDMDev = pDevice;
+
+               if (SysInitialise() != PVRSRV_OK)
+               {
+                       return -ENODEV;
+               }
+       }
+
+       return 0;
+}
+
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+{
+       SYS_DATA *psSysData;
+
+       PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+
+       SysAcquireData(&psSysData);
+       
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+       if (gPVRPowerLevel != 0)
+       {
+               if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+               {
+                       gPVRPowerLevel = 0;
+               }
+       }
+#endif
+       (IMG_VOID)SysDeinitialise(psSysData);
+
+       gpsPVRLDMDev = IMG_NULL;
+
+#if 0
+       if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+       {
+               return -EINVAL;
+       }
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+       return 0;
+#endif
+#if defined (PVR_LDM_PCI_MODULE)
+       return;
+#endif
+}
+
+
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *pDevice)
+{
+       PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+       (IMG_VOID) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+}
+
+#endif 
+
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+#if defined(SUPPORT_DRI_DRM)
+int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#else
+static int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+       PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
+       printk(KERN_ALERT  "PVRSRVDriverSuspend(pDevice=%p)", pDevice);
+
+       if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+       {
+               return -EINVAL;
+       }
+#endif
+       return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+int PVRSRVDriverResume(struct drm_device *pDevice)
+#else
+static int PVRSRVDriverResume(LDM_DEV *pDevice)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+       PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
+       printk(KERN_ALERT "PVRSRVDriverResume(pDevice=%p)", pDevice);
+
+       if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+       {
+               return -EINVAL;
+       }
+#endif
+       return 0;
+}
+#endif 
+
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+       IMG_CHAR data_buffer[2];
+       IMG_UINT32 PVRPowerLevel;
+
+       if (count != sizeof(data_buffer))
+       {
+               return -EINVAL;
+       }
+       else
+       {
+               if (copy_from_user(data_buffer, buffer, count))
+                       return -EINVAL;
+               if (data_buffer[count - 1] != '\n')
+                       return -EINVAL;
+               PVRPowerLevel = data_buffer[0] - '0';
+               if (PVRPowerLevel != gPVRPowerLevel)
+               {
+                       if (PVRPowerLevel != 0)
+                       {
+                               if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+                               {
+                                       return -EINVAL;
+                               }
+                       }
+                       else
+                       {
+                               if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+                               {
+                                       return -EINVAL;
+                               }
+                       }
+
+                       gPVRPowerLevel = PVRPowerLevel;
+               }
+       }
+       return (count);
+}
+
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)    
+{
+       seq_printf(sfile, "%lu\n", gPVRPowerLevel);
+}
+
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+       PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+       IMG_HANDLE hBlockAlloc;
+       int iRet = -ENOMEM;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32PID;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+#endif
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       ui32PID = OSGetCurrentProcessIDKM();
+
+       if (PVRSRVProcessConnect(ui32PID, 0) != PVRSRV_OK)
+               goto err_unlock;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       psEnvPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+       if (psEnvPerProc == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: No per-process private data", __FUNCTION__));
+               goto err_unlock;
+       }
+#endif
+
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                               sizeof(PVRSRV_FILE_PRIVATE_DATA),
+                                               (IMG_PVOID *)&psPrivateData,
+                                               &hBlockAlloc,
+                                               "File Private Data");
+
+       if(eError != PVRSRV_OK)
+               goto err_unlock;
+
+       psPrivateData->sec_fd_exp_meminfo = NULL;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       psPrivateData->psDRMFile = pFile;
+
+       list_add_tail(&psPrivateData->sDRMAuthListItem, &psEnvPerProc->sDRMAuthListHead);
+#endif 
+       psPrivateData->ui32OpenPID = ui32PID;
+       psPrivateData->hBlockAlloc = hBlockAlloc;
+       PRIVATE_DATA(pFile) = psPrivateData;
+       iRet = 0;
+err_unlock:    
+       LinuxUnLockMutex(&gPVRSRVLock);
+       return iRet;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+void PVRSRVRelease(void *pvPrivData)
+#else
+static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+       PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+       psPrivateData = (PVRSRV_FILE_PRIVATE_DATA *)pvPrivData;
+#else
+       psPrivateData = PRIVATE_DATA(pFile);
+#endif
+       if (psPrivateData != IMG_NULL)
+{
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       list_del(&psPrivateData->sDRMAuthListItem);
+#endif
+
+       
+       gui32ReleasePID = psPrivateData->ui32OpenPID;
+       PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
+       gui32ReleasePID = 0;
+
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                         sizeof(PVRSRV_FILE_PRIVATE_DATA),
+                         psPrivateData, psPrivateData->hBlockAlloc);
+
+#if !defined(SUPPORT_DRI_DRM)
+               PRIVATE_DATA(pFile) = IMG_NULL;
+#endif
+       }
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+
+#if !defined(SUPPORT_DRI_DRM)
+       return 0;
+#endif
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+int PVRCore_Init(IMG_VOID)
+#else
+static int __init PVRCore_Init(IMG_VOID)
+#endif
+{
+       int error;
+#if !defined(PVR_LDM_MODULE)
+       PVRSRV_ERROR eError;
+#else
+       struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+       
+       PVRDPFInit();
+#endif
+       PVR_TRACE(("PVRCore_Init"));
+
+       LinuxInitMutex(&gPVRSRVLock);
+
+       if (CreateProcEntries ())
+       {
+               error = -ENOMEM;
+               return error;
+       }
+
+       if (PVROSFuncInit() != PVRSRV_OK)
+       {
+               error = -ENOMEM;
+               goto init_failed;
+       }
+
+       PVRLinuxMUtilsInit();
+
+       if(LinuxMMInit() != PVRSRV_OK)
+       {
+               error = -ENOMEM;
+               goto init_failed;
+       }
+
+       LinuxBridgeInit();
+
+       PVRMMapInit();
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+       if ((error = platform_driver_register(&powervr_driver)) != 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error));
+
+               goto init_failed;
+       }
+
+#if defined(MODULE)
+       if ((error = platform_device_register(&powervr_device)) != 0)
+       {
+               platform_driver_unregister(&powervr_driver);
+
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error));
+
+               goto init_failed;
+       }
+#endif
+#endif 
+
+#if defined(PVR_LDM_PCI_MODULE)
+       if ((error = pci_register_driver(&powervr_driver)) != 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
+
+               goto init_failed;
+       }
+#endif 
+
+#else 
+       
+       if ((eError = SysInitialise()) != PVRSRV_OK)
+       {
+               error = -ENODEV;
+#if defined(TCF_REV) && (TCF_REV == 110)
+               if(eError == PVRSRV_ERROR_NOT_SUPPORTED)
+               {
+                       printk("\nAtlas wrapper (FPGA image) version mismatch");
+                       error = -ENODEV;
+               }
+#endif
+               goto init_failed;
+       }
+#endif 
+
+#if !defined(SUPPORT_DRI_DRM)
+       AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
+
+       if (AssignedMajorNumber <= 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number"));
+
+               error = -EBUSY;
+               goto sys_deinit;
+       }
+
+       PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
+#endif 
+
+#if defined(PVR_LDM_MODULE)
+       
+       psPvrClass = class_create(THIS_MODULE, "pvr");
+
+       if (IS_ERR(psPvrClass))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass)));
+               error = -EBUSY;
+               goto unregister_device;
+       }
+
+       psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+                                 NULL,
+#endif 
+                                 DEVNAME);
+       if (IS_ERR(psDev))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev)));
+               error = -EBUSY;
+               goto destroy_class;
+       }
+#endif 
+
+       pvr_debugfs_init();
+
+       return 0;
+
+#if defined(PVR_LDM_MODULE)
+destroy_class:
+       class_destroy(psPvrClass);
+unregister_device:
+       unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+#endif
+#if !defined(SUPPORT_DRI_DRM)
+sys_deinit:
+#endif
+#if defined(PVR_LDM_MODULE)
+#if defined(PVR_LDM_PCI_MODULE)
+       pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined (MODULE)
+       platform_device_unregister(&powervr_device);
+#endif
+       platform_driver_unregister(&powervr_driver);
+#endif
+
+#else  
+       
+       {
+               SYS_DATA *psSysData;
+
+               psSysData = SysAcquireDataNoCheck();
+               if (psSysData != IMG_NULL)
+               {
+                       (IMG_VOID)SysDeinitialise(psSysData);
+               }
+       }
+#endif 
+init_failed:
+       PVRMMapCleanup();
+       LinuxMMCleanup();
+       LinuxBridgeDeInit();
+       PVROSFuncDeInit();
+       RemoveProcEntries();
+
+       return error;
+
+} 
+
+
+#if defined(SUPPORT_DRI_DRM)
+void PVRCore_Cleanup(void)
+#else
+static void __exit PVRCore_Cleanup(void)
+#endif
+{
+       SYS_DATA *psSysData;
+
+       PVR_TRACE(("PVRCore_Cleanup"));
+
+       pvr_debugfs_cleanup();
+
+       SysAcquireData(&psSysData);
+
+#if defined(PVR_LDM_MODULE)
+       device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+       class_destroy(psPvrClass);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+       if (
+#endif 
+               unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME)
+#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+                                                               ;
+#else  
+                                                               )
+       {
+               PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber));
+       }
+#endif 
+#endif 
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PCI_MODULE)
+       pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined (MODULE)
+       platform_device_unregister(&powervr_device);
+#endif
+       platform_driver_unregister(&powervr_driver);
+#endif
+
+#else 
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+       if (gPVRPowerLevel != 0)
+       {
+               if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+               {
+                       gPVRPowerLevel = 0;
+               }
+       }
+#endif
+       
+       (void) SysDeinitialise(psSysData);
+#endif 
+
+       PVRMMapCleanup();
+
+       LinuxMMCleanup();
+
+       LinuxBridgeDeInit();
+
+       PVROSFuncDeInit();
+
+       RemoveProcEntries();
+
+       PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+#if !defined(SUPPORT_DRI_DRM)
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutex.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutex.c
new file mode 100644 (file)
index 0000000..e0b1d3e
--- /dev/null
@@ -0,0 +1,131 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/errno.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/module.h>
+
+#include <img_defs.h>
+#include <services.h>
+
+#include "mutex.h"
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    mutex_lock(psPVRSRVMutex);
+}
+
+PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    if(mutex_lock_interruptible(psPVRSRVMutex) == -EINTR)
+    {
+        return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
+    }
+    else
+    {
+        return PVRSRV_OK;
+    }
+}
+
+IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    return mutex_trylock(psPVRSRVMutex);
+}
+
+IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    mutex_unlock(psPVRSRVMutex);
+}
+
+IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    return (mutex_is_locked(psPVRSRVMutex)) ? IMG_TRUE : IMG_FALSE;
+}
+
+
+#else 
+
+
+IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    init_MUTEX(&psPVRSRVMutex->sSemaphore);
+    atomic_set(&psPVRSRVMutex->Count, 0);
+}
+
+IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    down(&psPVRSRVMutex->sSemaphore);
+    atomic_dec(&psPVRSRVMutex->Count);
+}
+
+PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    if(down_interruptible(&psPVRSRVMutex->sSemaphore) == -EINTR)
+    {
+        
+        return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
+    }else{
+        atomic_dec(&psPVRSRVMutex->Count);
+        return PVRSRV_OK;
+    }
+}
+
+IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    IMG_INT32 Status = down_trylock(&psPVRSRVMutex->sSemaphore);
+    if(Status == 0)
+    {
+        atomic_dec(&psPVRSRVMutex->Count);
+    }
+
+    return Status;
+}
+
+IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    atomic_inc(&psPVRSRVMutex->Count);
+    up(&psPVRSRVMutex->sSemaphore);
+}
+
+IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    IMG_INT32 iCount;
+    
+    iCount = atomic_read(&psPVRSRVMutex->Count);
+
+    return (IMG_BOOL)iCount;
+}
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutex.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutex.h
new file mode 100644 (file)
index 0000000..3138638
--- /dev/null
@@ -0,0 +1,77 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __INCLUDED_LINUX_MUTEX_H_
+#define __INCLUDED_LINUX_MUTEX_H_
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+typedef struct mutex PVRSRV_LINUX_MUTEX;
+
+#else 
+
+
+typedef struct {
+    struct semaphore sSemaphore;
+    
+    atomic_t Count;
+}PVRSRV_LINUX_MUTEX;
+
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+#define LinuxInitMutex(psPVRSRVMutex) \
+       do { \
+               mutex_init(psPVRSRVMutex); \
+       } while(0)
+#else
+extern IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+#endif
+
+extern IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutils.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutils.c
new file mode 100644 (file)
index 0000000..d9ad5ff
--- /dev/null
@@ -0,0 +1,130 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mutils.h"
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+#define        PAT_LINUX_X86_WC        1
+
+#define        PAT_X86_ENTRY_BITS      8
+
+#define        PAT_X86_BIT_PWT         1U
+#define        PAT_X86_BIT_PCD         2U
+#define        PAT_X86_BIT_PAT         4U
+#define        PAT_X86_BIT_MASK        (PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT)
+
+static IMG_BOOL g_write_combining_available = IMG_FALSE;
+
+#define        PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0)
+
+static inline IMG_UINT
+pvr_pat_index(pgprotval_t prot_val)
+{
+       IMG_UINT ret = 0;
+       pgprotval_t val = prot_val & _PAGE_CACHE_MASK;
+
+       ret |= PROT_TO_PAT_INDEX(val, PAT);
+       ret |= PROT_TO_PAT_INDEX(val, PCD);
+       ret |= PROT_TO_PAT_INDEX(val, PWT);
+
+       return ret;
+}
+
+static inline IMG_UINT
+pvr_pat_entry(u64 pat, IMG_UINT index)
+{
+       return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK;
+}
+
+static IMG_VOID
+PVRLinuxX86PATProbe(IMG_VOID)
+{
+       
+       if (cpu_has_pat)         
+       {
+               u64 pat;
+               IMG_UINT pat_index;
+               IMG_UINT pat_entry;
+
+               PVR_TRACE(("%s: PAT available", __FUNCTION__));
+               
+               rdmsrl(MSR_IA32_CR_PAT, pat);
+               PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
+               PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
+
+               pat_index = pvr_pat_index(_PAGE_CACHE_WC);
+               PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index));
+
+               pat_entry = pvr_pat_entry(pat, pat_index);
+               PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC));
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+               g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC);
+#endif
+       }
+#if defined(DEBUG)
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+       if (g_write_combining_available)
+       {
+               PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__));
+       }
+       else
+       {
+               PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
+       }
+#else  
+       PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
+#endif 
+#endif 
+}
+
+pgprot_t
+pvr_pgprot_writecombine(pgprot_t prot)
+{
+    
+     
+    return (g_write_combining_available) ?
+               __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
+}
+#endif 
+
+IMG_VOID
+PVRLinuxMUtilsInit(IMG_VOID)
+{
+#if defined(SUPPORT_LINUX_X86_PAT)
+       PVRLinuxX86PATProbe();
+#endif
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutils.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mutils.h
new file mode 100644 (file)
index 0000000..24c199a
--- /dev/null
@@ -0,0 +1,97 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#include <linux/version.h>
+
+#if !(defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)))
+#if defined(SUPPORT_LINUX_X86_PAT)
+#undef SUPPORT_LINUX_X86_PAT
+#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+       pgprot_t pvr_pgprot_writecombine(pgprot_t prot);
+       #define PGPROT_WC(pv)   pvr_pgprot_writecombine(pv)
+#else
+       #if defined(__arm__) || defined(__sh__)
+               #define PGPROT_WC(pv)   pgprot_writecombine(pv)
+       #else
+               #if defined(__i386__) || defined(__mips__)
+                       #define PGPROT_WC(pv)   pgprot_noncached(pv)
+               #else
+                       #define PGPROT_WC(pv)   pgprot_noncached(pv)
+                       #error  Unsupported architecture!
+               #endif
+       #endif
+#endif
+
+#define        PGPROT_UC(pv)   pgprot_noncached(pv)
+
+#if defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+       #define IOREMAP(pa, bytes)      ioremap_cache(pa, bytes)
+#else  
+       #if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+               #define IOREMAP(pa, bytes)      ioremap_cached(pa, bytes)
+       #else
+               #define IOREMAP(pa, bytes)      ioremap(pa, bytes)
+       #endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+       #if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+               #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+       #else
+               #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+       #endif
+#else
+       #if defined(__arm__)
+               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+                       #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+               #else
+                       #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+                               #define IOREMAP_WC(pa, bytes)   ioremap_nocache(pa, bytes)
+                       #else
+                               #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17))
+                                       #define IOREMAP_WC(pa, bytes)   __ioremap(pa, bytes, L_PTE_BUFFERABLE)
+                               #else
+                                       #define IOREMAP_WC(pa, bytes)   __ioremap(pa, bytes, , L_PTE_BUFFERABLE, 1)
+                               #endif
+                       #endif
+               #endif
+       #else
+               #define IOREMAP_WC(pa, bytes)   ioremap_nocache(pa, bytes)
+       #endif
+#endif
+
+#define        IOREMAP_UC(pa, bytes)   ioremap_nocache(pa, bytes)
+
+IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/osfunc.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/osfunc.c
new file mode 100644 (file)
index 0000000..04b55b4
--- /dev/null
@@ -0,0 +1,3006 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+#include <asm/cacheflush.h>
+#endif
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \
+       defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \
+       defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \
+       defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) || \
+       defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "event.h"
+#include "linkage.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
+#else
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
+#endif
+
+#if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT)
+#error "A preemptible Linux kernel is required when using workqueues"
+#endif
+
+#define EVENT_OBJECT_TIMEOUT_MS                (100)
+
+#define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0)
+#define HOST_ALLOC_MEM_USING_VMALLOC ((IMG_HANDLE)1)
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
+#else
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+    PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line);
+#else
+    *ppvCpuVAddr = KMallocWrapper(ui32Size);
+#endif
+    if(*ppvCpuVAddr)
+    {
+    if (phBlockAlloc)
+    {
+
+        *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
+    }
+    }
+    else
+    {
+    if (!phBlockAlloc)
+    {
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
+#else
+    *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
+#endif
+    if (!*ppvCpuVAddr)
+    {
+         return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+
+    *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
+    }
+
+    return PVRSRV_OK;
+}
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+
+static inline int is_vmalloc_addr(const void *pvCpuVAddr)
+{
+       unsigned long lAddr = (unsigned long)pvCpuVAddr;
+       return lAddr >= VMALLOC_START && lAddr < VMALLOC_END;
+}
+
+#endif
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+#else
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+    PVR_UNREFERENCED_PARAMETER(ui32Flags);
+    PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+    if (hBlockAlloc == HOST_ALLOC_MEM_USING_VMALLOC)
+    {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+    VFreeWrapper(pvCpuVAddr);
+#endif
+    }
+    else
+    {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+        KFreeWrapper(pvCpuVAddr);
+#endif
+    }
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
+                                 IMG_UINT32 ui32Size,
+                                 IMG_UINT32 ui32PageSize,
+                                 IMG_VOID **ppvCpuVAddr,
+                                 IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+#if 0
+
+    if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
+    {
+        ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+        ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS;
+    }
+#endif
+
+    switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+            psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+
+
+            psLinuxMemArea = NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+            ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+            psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n", ui32AllocFlags));
+            *ppvCpuVAddr = NULL;
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+    *phOSMemHandle = psLinuxMemArea;
+
+    LinuxMemAreaRegister(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+
+    PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+            eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+            if (eError != PVRSRV_OK)
+            {
+                PVR_DPF((PVR_DBG_ERROR,
+                         "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%d, "
+                                        "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
+                         ui32AllocFlags, ui32Bytes, pvCpuVAddr, hOSMemHandle));
+                return eError;
+            }
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"%s: invalid flags 0x%x\n",
+                    __FUNCTION__, ui32AllocFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+                  IMG_UINT32 ui32ByteOffset,
+                  IMG_UINT32 ui32Bytes,
+                  IMG_UINT32 ui32Flags,
+                  IMG_HANDLE *phOSMemHandleRet)
+{
+    LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+
+    psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
+    if(!psLinuxMemArea)
+    {
+        *phOSMemHandleRet = NULL;
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+    *phOSMemHandleRet = psLinuxMemArea;
+
+
+    if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+        return PVRSRV_OK;
+    }
+
+    eError = PVRMMapRegisterArea(psLinuxMemArea);
+    if(eError != PVRSRV_OK)
+     {
+        goto failed_register_area;
+    }
+
+    return PVRSRV_OK;
+
+failed_register_area:
+    *phOSMemHandleRet = NULL;
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+    return eError;
+}
+
+PVRSRV_ERROR
+OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+    if((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0)
+    {
+        eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+        if(eError != PVRSRV_OK)
+        {
+            return eError;
+        }
+    }
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+IMG_CPU_PHYADDR
+OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset)
+{
+    PVR_ASSERT(hOSMemHandle);
+
+    return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+}
+
+
+
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+    IMG_UINT8 *Src,*Dst;
+    IMG_INT i;
+
+    Src=(IMG_UINT8 *)pvSrc;
+    Dst=(IMG_UINT8 *)pvDst;
+    for(i=0;i<ui32Size;i++)
+    {
+        Dst[i]=Src[i];
+    }
+#else
+    memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMSET)
+    IMG_UINT8 *Buff;
+    IMG_INT i;
+
+    Buff=(IMG_UINT8 *)pvDest;
+    for(i=0;i<ui32Size;i++)
+    {
+        Buff[i]=ui8Value;
+    }
+#else
+    memset(pvDest, (IMG_INT) ui8Value, (size_t) ui32Size);
+#endif
+}
+
+
+IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
+{
+    return (strcpy(pszDest, pszSrc));
+}
+
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
+{
+    va_list argList;
+    IMG_INT32 iCount;
+
+    va_start(argList, pszFormat);
+    iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList);
+    va_end(argList);
+
+    return iCount;
+}
+
+IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+    if(*pui32Access)
+    {
+        if(psResource->ui32ID == ui32ID)
+        {
+            psResource->ui32ID = 0;
+            *pui32Access = 0;
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked for this process."));
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked"));
+    }
+}
+
+
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
+{
+    psResource->ui32ID = 0;
+    psResource->ui32Lock = 0;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
+{
+    OSBreakResourceLock (psResource, psResource->ui32ID);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
+{
+    ENV_DATA           *psEnvData;
+    PVRSRV_ERROR       eError;
+
+
+    eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
+        "Environment Data");
+    if (eError != PVRSRV_OK)
+    {
+        return eError;
+    }
+
+    eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
+                    &psEnvData->pvBridgeData, IMG_NULL,
+                    "Bridge Data");
+    if (eError != PVRSRV_OK)
+    {
+        OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
+
+        return eError;
+    }
+
+
+
+    psEnvData->bMISRInstalled = IMG_FALSE;
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+
+    *ppvEnvSpecificData = psEnvData;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
+{
+    ENV_DATA           *psEnvData = (ENV_DATA*)pvEnvSpecificData;
+
+    PVR_ASSERT(!psEnvData->bMISRInstalled);
+    PVR_ASSERT(!psEnvData->bLISRInstalled);
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, psEnvData->pvBridgeData, IMG_NULL);
+    psEnvData->pvBridgeData = IMG_NULL;
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
+
+
+    return PVRSRV_OK;
+}
+
+
+
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
+{
+    schedule();
+}
+
+
+
+IMG_UINT32 OSClockus(IMG_VOID)
+{
+    IMG_UINT32 time, j = jiffies;
+
+    time = j * (1000000 / HZ);
+
+    return time;
+}
+
+
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
+{
+    udelay(ui32Timeus);
+}
+
+
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems)
+{
+    msleep(ui32Timems);
+}
+
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
+{
+    if (in_interrupt())
+    {
+        return KERNEL_ID;
+    }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+    return (IMG_UINT32)current->pgrp;
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+    return (IMG_UINT32)task_tgid_nr(current);
+#else
+    return (IMG_UINT32)current->tgid;
+#endif
+#endif
+}
+
+
+IMG_UINT32 OSGetPageSize(IMG_VOID)
+{
+#if defined(__sh__)
+    IMG_UINT32 ui32ReturnValue = PAGE_SIZE;
+
+    return (ui32ReturnValue);
+#else
+    return PAGE_SIZE;
+#endif
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+        , struct pt_regs *regs
+#endif
+        )
+{
+    PVRSRV_DEVICE_NODE *psDeviceNode;
+    IMG_BOOL bStatus = IMG_FALSE;
+
+    PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+    PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+    psDeviceNode = (PVRSRV_DEVICE_NODE*)dev_id;
+    if(!psDeviceNode)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n"));
+        goto out;
+    }
+
+    bStatus = PVRSRVDeviceLISR(psDeviceNode);
+
+    if (bStatus)
+    {
+               OSScheduleMISR((IMG_VOID *)psDeviceNode->psSysData);
+    }
+
+out:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+    return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+
+
+
+static irqreturn_t SystemISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+        , struct pt_regs *regs
+#endif
+        )
+{
+    SYS_DATA *psSysData;
+    IMG_BOOL bStatus = IMG_FALSE;
+
+    PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+    PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+    psSysData = (SYS_DATA *)dev_id;
+    if(!psSysData)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "SystemISRWrapper: invalid params\n"));
+        goto out;
+    }
+
+    bStatus = PVRSRVSystemLISR(psSysData);
+
+    if (bStatus)
+    {
+        OSScheduleMISR((IMG_VOID *)psSysData);
+    }
+
+out:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+    return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+                                    IMG_UINT32 ui32Irq,
+                                    IMG_CHAR *pszISRName,
+                                    IMG_VOID *pvDeviceNode)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+        return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+    }
+
+    PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %p", pszISRName, ui32Irq, pvDeviceNode));
+
+    if(request_irq(ui32Irq, DeviceISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+        SA_SHIRQ
+#else
+        IRQF_SHARED
+#endif
+        , pszISRName, pvDeviceNode))
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", ui32Irq));
+
+        return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+    }
+
+    psEnvData->ui32IRQ = ui32Irq;
+    psEnvData->pvISRCookie = pvDeviceNode;
+    psEnvData->bLISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallDeviceLISR: No LISR has been installed"));
+        return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+    }
+
+    PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ,  psEnvData->pvISRCookie));
+
+    free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+        return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+    }
+
+    PVR_TRACE(("Installing system LISR on IRQ %d with cookie %p", ui32Irq, pvSysData));
+
+    if(request_irq(ui32Irq, SystemISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+        SA_SHIRQ
+#else
+        IRQF_SHARED
+#endif
+        , "PowerVR", pvSysData))
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Couldn't install system LISR on IRQ %d", ui32Irq));
+
+        return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+    }
+
+    psEnvData->ui32IRQ = ui32Irq;
+    psEnvData->pvISRCookie = pvSysData;
+    psEnvData->bLISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallSystemLISR: No LISR has been installed"));
+        return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+    }
+
+    PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+    free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+    return PVRSRV_OK;
+}
+
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+                       void *data
+#else
+                       struct work_struct *data
+#endif
+)
+{
+       ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+       SYS_DATA *psSysData  = (SYS_DATA *)psEnvData->pvMISRData;
+
+       PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+       if (psEnvData->bMISRInstalled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+               return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+       }
+
+       PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+       psEnvData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
+
+       if (psEnvData->psWorkQueue == IMG_NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed"));
+               return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+       }
+
+       INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+               , (void *)&psEnvData->sMISRWork
+#endif
+                               );
+
+       psEnvData->pvMISRData = pvSysData;
+       psEnvData->bMISRInstalled = IMG_TRUE;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+       if (!psEnvData->bMISRInstalled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+               return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+       }
+
+       PVR_TRACE(("Uninstalling MISR"));
+
+       destroy_workqueue(psEnvData->psWorkQueue);
+
+       psEnvData->bMISRInstalled = IMG_FALSE;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+       if (psEnvData->bMISRInstalled)
+       {
+               queue_work(psEnvData->psWorkQueue, &psEnvData->sMISRWork);
+       }
+
+       return PVRSRV_OK;
+}
+#else
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+                       void *data
+#else
+                       struct work_struct *data
+#endif
+)
+{
+       ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+       SYS_DATA *psSysData  = (SYS_DATA *)psEnvData->pvMISRData;
+
+       PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+       if (psEnvData->bMISRInstalled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+               return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+       }
+
+       PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+       INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+               , (void *)&psEnvData->sMISRWork
+#endif
+                               );
+
+       psEnvData->pvMISRData = pvSysData;
+       psEnvData->bMISRInstalled = IMG_TRUE;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+       if (!psEnvData->bMISRInstalled)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+               return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+       }
+
+       PVR_TRACE(("Uninstalling MISR"));
+
+       flush_scheduled_work();
+
+       psEnvData->bMISRInstalled = IMG_FALSE;
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+       SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+       ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+       if (psEnvData->bMISRInstalled)
+       {
+               schedule_work(&psEnvData->sMISRWork);
+       }
+
+       return PVRSRV_OK;
+}
+
+#else
+
+
+static void MISRWrapper(unsigned long data)
+{
+    SYS_DATA *psSysData;
+
+    psSysData = (SYS_DATA *)data;
+
+    PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bMISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+        return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+    }
+
+    PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+    tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, (unsigned long)pvSysData);
+
+    psEnvData->bMISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bMISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+        return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+    }
+
+    PVR_TRACE(("Uninstalling MISR"));
+
+    tasklet_kill(&psEnvData->sMISRTasklet);
+
+    psEnvData->bMISRInstalled = IMG_FALSE;
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bMISRInstalled)
+    {
+        tasklet_schedule(&psEnvData->sMISRTasklet);
+    }
+
+    return PVRSRV_OK;
+}
+
+#endif
+#endif
+
+#endif
+
+IMG_VOID OSPanic(IMG_VOID)
+{
+       BUG();
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#define        OS_TAS(p)       xchg((p), 1)
+#else
+#define        OS_TAS(p)       tas(p)
+#endif
+PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE  *psResource,
+                                IMG_UINT32                     ui32ID)
+
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(!OS_TAS(&psResource->ui32Lock))
+        psResource->ui32ID = ui32ID;
+    else
+        eError = PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE;
+
+    return eError;
+}
+
+
+PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(*pui32Access)
+    {
+        if(psResource->ui32ID == ui32ID)
+        {
+            psResource->ui32ID = 0;
+               smp_mb();
+            *pui32Access = 0;
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked with expected value.", psResource));
+            PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID));
+            eError = PVRSRV_ERROR_INVALID_LOCK_ID;
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked", psResource));
+        eError = PVRSRV_ERROR_RESOURCE_NOT_LOCKED;
+    }
+
+    return eError;
+}
+
+
+       IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+    return     (*(volatile IMG_UINT32 *)pui32Access == 1) && (psResource->ui32ID == ui32ID)
+            ?  IMG_TRUE
+            :  IMG_FALSE;
+}
+
+
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
+                                                                 IMG_VOID *pvLinAddr)
+{
+    IMG_CPU_PHYADDR CpuPAddr;
+    LinuxMemArea *psLinuxMemArea;
+       IMG_UINTPTR_T uiByteOffset;
+       IMG_UINT32 ui32ByteOffset;
+
+       PVR_ASSERT(hOSMemHandle != IMG_NULL);
+
+
+
+       psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+       uiByteOffset = (IMG_UINTPTR_T)pvLinAddr - (IMG_UINTPTR_T)LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+       ui32ByteOffset = (IMG_UINT32)uiByteOffset;
+
+       CpuPAddr = LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+
+       return CpuPAddr;
+}
+
+
+IMG_VOID *
+OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+               IMG_UINT32 ui32Bytes,
+               IMG_UINT32 ui32MappingFlags,
+               IMG_HANDLE *phOSMemHandle)
+{
+    if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+
+       if(phOSMemHandle == IMG_NULL)
+       {
+               IMG_VOID *pvIORemapCookie;
+               pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
+               if(pvIORemapCookie == IMG_NULL)
+               {
+                   return IMG_NULL;
+               }
+               return pvIORemapCookie;
+       }
+       else
+       {
+               LinuxMemArea *psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+
+               if(psLinuxMemArea == IMG_NULL)
+               {
+                   return IMG_NULL;
+               }
+
+               *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+               return LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+       }
+    }
+
+    PVR_DPF((PVR_DBG_ERROR,
+             "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+             " (Use OSReservePhys otherwise)"));
+
+    return IMG_NULL;
+}
+
+IMG_BOOL
+OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
+{
+    PVR_TRACE(("%s: unmapping %d bytes from %p", __FUNCTION__, ui32Bytes, pvLinAddr));
+
+    PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+    if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+        if (hOSMemHandle == IMG_NULL)
+       {
+               IOUnmapWrapper(pvLinAddr);
+       }
+       else
+       {
+               LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+               PVR_ASSERT(LinuxMemAreaToCpuVAddr(psLinuxMemArea) == pvLinAddr);
+
+               FreeIORemapLinuxMemArea(psLinuxMemArea);
+       }
+
+        return IMG_TRUE;
+    }
+
+    PVR_DPF((PVR_DBG_ERROR,
+                 "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+                 " (Use OSUnReservePhys otherwise)"));
+    return IMG_FALSE;
+}
+
+static PVRSRV_ERROR
+RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
+          IMG_VOID *pvCPUVAddr,
+              IMG_UINT32 ui32Bytes,
+          IMG_BOOL bPhysContig,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+            ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"OSRegisterMem : invalid flags 0x%x\n", ui32MappingFlags));
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_INVALID_FLAGS;
+    }
+
+    *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+
+    LinuxMemAreaRegister(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+              IMG_VOID *pvCPUVAddr,
+              IMG_UINT32 ui32Bytes,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_HANDLE *phOSMemHandle)
+{
+    IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
+
+    return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
+{
+    return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR
+OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
+                IMG_UINT32 ui32Bytes,
+                IMG_UINT32 ui32MappingFlags,
+                IMG_HANDLE hOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    PVRSRV_ERROR eError;
+
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+    PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+            if (eError != PVRSRV_OK)
+            {
+                 PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+                          __FUNCTION__, pvCpuVAddr, ui32Bytes,
+                          ui32MappingFlags, hOSMemHandle));
+                return eError;
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSUnRegisterMem : invalid flags 0x%x", ui32MappingFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+    return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+}
+
+PVRSRV_ERROR
+OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
+              IMG_UINT32 ui32Bytes,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_VOID **ppvCpuVAddr,
+              IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+#if 0
+
+    if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
+    {
+        ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+        ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS;
+    }
+#endif
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+
+            psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+
+            psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+            ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+            psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"OSMapPhysToLin : invalid flags 0x%x\n", ui32MappingFlags));
+            *ppvCpuVAddr = NULL;
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_INVALID_FLAGS;
+    }
+
+    *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+    *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+    LinuxMemAreaRegister(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+OSUnReservePhys(IMG_VOID *pvCpuVAddr,
+                IMG_UINT32 ui32Bytes,
+                IMG_UINT32 ui32MappingFlags,
+                IMG_HANDLE hOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+    PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+            if (eError != PVRSRV_OK)
+            {
+                 PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+                          __FUNCTION__, pvCpuVAddr, ui32Bytes,
+                          ui32MappingFlags, hOSMemHandle));
+                return eError;
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSUnMapPhysToLin : invalid flags 0x%x", ui32MappingFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+    PVR_UNREFERENCED_PARAMETER(ui32Size);
+    PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+    PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
+
+    return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+    IMG_VOID *pvKernLinAddr;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    pvKernLinAddr = _KMallocWrapper(ui32Size, __FILE__, __LINE__);
+#else
+    pvKernLinAddr = KMallocWrapper(ui32Size);
+#endif
+    if (!pvKernLinAddr)
+    {
+    return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+    *pvLinAddr = pvKernLinAddr;
+
+    psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
+
+    return PVRSRV_OK;
+#endif
+}
+
+
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+    PVR_UNREFERENCED_PARAMETER(ui32Size);
+    PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+    PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
+#else
+    PVR_UNREFERENCED_PARAMETER(ui32Size);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+    KFreeWrapper(pvLinAddr);
+#endif
+    return PVRSRV_OK;
+}
+
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+    return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+    return *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+    writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+    *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+#endif
+}
+
+#if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
+{
+    int err;
+    IMG_UINT32 i;
+    PVR_PCI_DEV *psPVRPCI;
+
+    PVR_TRACE(("OSPCISetDev"));
+
+    if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID **)&psPVRPCI, IMG_NULL,
+        "PCI Device") != PVRSRV_OK)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't allocate PVR PCI structure"));
+        return IMG_NULL;
+    }
+
+    psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
+    psPVRPCI->ePCIFlags = eFlags;
+
+    err = pci_enable_device(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't enable device (%d)", err));
+        return IMG_NULL;
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+    {
+        pci_set_master(psPVRPCI->psPCIDev);
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+    {
+#if defined(CONFIG_PCI_MSI)
+       if (psPVRPCI->psPCIDev->device == PSB_SYS_SGX_DEV_DEVICE_ID_1 ||
+           psPVRPCI->psPCIDev->device == PSB_SYS_SGX_DEV_DEVICE_ID_2) // Disable MSI for Menlow
+               psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+       else if(!psPVRPCI->psPCIDev->msi_enabled)
+       {
+               err = pci_enable_msi(psPVRPCI->psPCIDev);
+               if (err != 0)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: Couldn't enable MSI (%d)", err));
+                       psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+               }
+       }
+#else
+        PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
+#endif
+    }
+
+
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+    }
+
+    return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
+}
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags)
+{
+    struct pci_dev *psPCIDev;
+
+    psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
+    if (psPCIDev == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIAcquireDev: Couldn't acquire device"));
+        return IMG_NULL;
+    }
+
+    return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
+}
+
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+    *pui32IRQ = psPVRPCI->psPCIDev->irq;
+
+    return PVRSRV_OK;
+}
+
+enum HOST_PCI_ADDR_RANGE_FUNC
+{
+    HOST_PCI_ADDR_RANGE_FUNC_LEN,
+    HOST_PCI_ADDR_RANGE_FUNC_START,
+    HOST_PCI_ADDR_RANGE_FUNC_END,
+    HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
+    HOST_PCI_ADDR_RANGE_FUNC_RELEASE
+};
+
+static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
+                                     PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+                                     IMG_UINT32 ui32Index)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+    if (ui32Index >= DEVICE_COUNT_RESOURCE)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Index out of range"));
+        return 0;
+
+    }
+
+    switch (eFunc)
+    {
+        case HOST_PCI_ADDR_RANGE_FUNC_LEN:
+            return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_START:
+            return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_END:
+            return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
+        {
+            int err;
+
+            err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, "PowerVR");
+            if (err != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err));
+                return 0;
+            }
+            psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
+            return 1;
+        }
+        case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
+            if (psPVRPCI->abPCIResourceInUse[ui32Index])
+            {
+                pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index);
+                psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
+            }
+            return 1;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Unknown function"));
+            break;
+    }
+
+    return 0;
+}
+
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index);
+}
+
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+                                   IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int i;
+
+    PVR_TRACE(("OSPCIReleaseDev"));
+
+
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i));
+            pci_release_region(psPVRPCI->psPCIDev, i);
+            psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+        }
+    }
+
+#if defined(CONFIG_PCI_MSI)
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+    {
+        pci_disable_msi(psPVRPCI->psPCIDev);
+    }
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+    {
+        pci_clear_master(psPVRPCI->psPCIDev);
+    }
+#endif
+    pci_disable_device(psPVRPCI->psPCIDev);
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
+
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int i;
+    int err;
+
+    PVR_TRACE(("OSPCISuspendDev"));
+
+
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            pci_release_region(psPVRPCI->psPCIDev, i);
+        }
+    }
+
+    err = pci_save_state(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_save_state_failed (%d)", err));
+        return PVRSRV_ERROR_PCI_CALL_FAILED;
+    }
+
+    pci_disable_device(psPVRPCI->psPCIDev);
+
+    err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND));
+    switch(err)
+    {
+        case 0:
+            break;
+        case -EIO:
+            PVR_DPF((PVR_DBG_WARNING, "OSPCISuspendDev: device doesn't support PCI PM"));
+            break;
+        case -EINVAL:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: can't enter requested power state"));
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_set_power_state failed (%d)", err));
+            break;
+    }
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int err;
+    int i;
+
+    PVR_TRACE(("OSPCIResumeDev"));
+
+    err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
+    switch(err)
+    {
+        case 0:
+            break;
+        case -EIO:
+            PVR_DPF((PVR_DBG_WARNING, "OSPCIResumeDev: device doesn't support PCI PM"));
+            break;
+        case -EINVAL:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: can't enter requested power state"));
+            return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_set_power_state failed (%d)", err));
+            return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+    }
+
+    pci_restore_state(psPVRPCI->psPCIDev);
+
+    err = pci_enable_device(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: Couldn't enable device (%d)", err));
+        return PVRSRV_ERROR_PCI_CALL_FAILED;
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+        pci_set_master(psPVRPCI->psPCIDev);
+
+
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            err = pci_request_region(psPVRPCI->psPCIDev, i, "PowerVR");
+            if (err != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)", i, err));
+            }
+        }
+
+    }
+
+    return PVRSRV_OK;
+}
+
+#endif
+
+#define        OS_MAX_TIMERS   8
+
+typedef struct TIMER_CALLBACK_DATA_TAG
+{
+    IMG_BOOL                   bInUse;
+    PFN_TIMER_FUNC             pfnTimerFunc;
+    IMG_VOID                   *pvData;
+    struct timer_list          sTimer;
+    IMG_UINT32                 ui32Delay;
+    IMG_BOOL                   bActive;
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    struct work_struct         sWork;
+#endif
+}TIMER_CALLBACK_DATA;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static struct workqueue_struct *psTimerWorkQueue;
+#endif
+
+static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+DEFINE_MUTEX(sTimerStructLock);
+#else
+
+static DEFINE_SPINLOCK(sTimerStructLock);
+#endif
+
+static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
+{
+    if (!psTimerCBData->bActive)
+        return;
+
+
+    psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+
+
+    mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
+{
+    TIMER_CALLBACK_DATA        *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    int res;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork);
+#else
+    res = schedule_work(&psTimerCBData->sWork);
+#endif
+    if (res == 0)
+    {
+        PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued"));
+    }
+#else
+    OSTimerCallbackBody(psTimerCBData);
+#endif
+}
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork);
+
+    OSTimerCallbackBody(psTimerCBData);
+}
+#endif
+
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
+{
+    TIMER_CALLBACK_DATA        *psTimerCBData;
+    IMG_UINT32         ui32i;
+#if !(defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE))
+    unsigned long              ulLockFlags;
+#endif
+
+
+    if(!pfnTimerFunc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
+        return IMG_NULL;
+    }
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    mutex_lock(&sTimerStructLock);
+#else
+    spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+#endif
+    for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+    {
+        psTimerCBData = &sTimers[ui32i];
+        if (!psTimerCBData->bInUse)
+        {
+            psTimerCBData->bInUse = IMG_TRUE;
+            break;
+        }
+    }
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    mutex_unlock(&sTimerStructLock);
+#else
+    spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+#endif
+    if (ui32i >= OS_MAX_TIMERS)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));
+        return IMG_NULL;
+    }
+
+    psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+    psTimerCBData->pvData = pvData;
+    psTimerCBData->bActive = IMG_FALSE;
+
+
+
+
+    psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+                                ?      1
+                                :      ((HZ * ui32MsTimeout) / 1000);
+
+    init_timer(&psTimerCBData->sTimer);
+
+
+
+    psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
+    psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
+
+    return (IMG_HANDLE)(ui32i + 1);
+}
+
+
+static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
+{
+    IMG_UINT32 ui32i = ((IMG_UINT32)hTimer) - 1;
+
+    PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+
+    return &sTimers[ui32i];
+}
+
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(!psTimerCBData->bActive);
+
+
+    psTimerCBData->bInUse = IMG_FALSE;
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(!psTimerCBData->bActive);
+
+
+    psTimerCBData->bActive = IMG_TRUE;
+
+
+    psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+
+    add_timer(&psTimerCBData->sTimer);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(psTimerCBData->bActive);
+
+
+    psTimerCBData->bActive = IMG_FALSE;
+    smp_mb();
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    flush_scheduled_work();
+#endif
+
+
+    del_timer_sync(&psTimerCBData->sTimer);
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+
+    flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    flush_scheduled_work();
+#endif
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *psEventObject)
+{
+
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(psEventObject)
+    {
+        if(pszName)
+        {
+
+            strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
+        }
+        else
+        {
+
+            static IMG_UINT16 ui16NameIndex = 0;
+            snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
+        }
+
+        if(LinuxEventObjectListCreate(&psEventObject->hOSEventKM) != PVRSRV_OK)
+        {
+             eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT;
+    }
+
+    return eError;
+
+}
+
+
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(psEventObject)
+    {
+        if(psEventObject->hOSEventKM)
+        {
+            LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: hOSEventKM is not a valid pointer"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    return eError;
+}
+
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError;
+
+    if(hOSEventKM)
+    {
+        eError = LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWait: hOSEventKM is not a valid handle"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    return eError;
+}
+
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+                                            IMG_HANDLE *phOSEvent)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(psEventObject)
+    {
+        if(LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) != PVRSRV_OK)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    return eError;
+}
+
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+                                            IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(psEventObject)
+    {
+        if(LinuxEventObjectDelete(psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    return eError;
+
+}
+
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError;
+
+    if(hOSEventKM)
+    {
+        eError = LinuxEventObjectSignal(hOSEventKM);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignal: hOSEventKM is not a valid handle"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    return eError;
+}
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
+{
+    /*
+     * Return true here so that we can run X as a non-root user.
+     */
+    return IMG_TRUE;
+}
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
+                          IMG_VOID *pvDest,
+                          IMG_VOID *pvSrc,
+                          IMG_UINT32 ui32Bytes)
+{
+    PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+    if(copy_to_user(pvDest, pvSrc, ui32Bytes)==0)
+        return PVRSRV_OK;
+    else
+        return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
+                             IMG_VOID *pvDest,
+                             IMG_VOID *pvSrc,
+                             IMG_UINT32 ui32Bytes)
+{
+    PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+    if(copy_from_user(pvDest, pvSrc, ui32Bytes)==0)
+        return PVRSRV_OK;
+    else
+        return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
+{
+    IMG_INT linuxType;
+
+    if (eVerification == PVR_VERIFY_READ)
+    {
+        linuxType = VERIFY_READ;
+    }
+    else
+    {
+        PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+        linuxType = VERIFY_WRITE;
+    }
+
+    return access_ok(linuxType, pvUserPtr, ui32Bytes);
+}
+
+typedef enum _eWrapMemType_
+{
+    WRAP_TYPE_NULL = 0,
+    WRAP_TYPE_GET_USER_PAGES,
+    WRAP_TYPE_FIND_VMA
+} eWrapMemType;
+
+typedef struct _sWrapMemInfo_
+{
+    eWrapMemType eType;
+    IMG_INT iNumPages;
+    IMG_INT iNumPagesMapped;
+    struct page **ppsPages;
+    IMG_SYS_PHYADDR *psPhysAddr;
+    IMG_INT iPageOffset;
+#if defined(DEBUG)
+    IMG_UINT32 ulStartAddr;
+    IMG_UINT32 ulBeyondEndAddr;
+    struct vm_area_struct *psVMArea;
+#endif
+} sWrapMemInfo;
+
+
+static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr, IMG_UINT32 *pulPFN, struct page **ppsPage)
+{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
+    pgd_t *psPGD;
+    pud_t *psPUD;
+    pmd_t *psPMD;
+    pte_t *psPTE;
+    struct mm_struct *psMM = psVMArea->vm_mm;
+    spinlock_t *psPTLock;
+    IMG_BOOL bRet = IMG_FALSE;
+
+    *pulPFN = 0;
+    *ppsPage = NULL;
+
+    psPGD = pgd_offset(psMM, ulCPUVAddr);
+    if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+        return bRet;
+
+    psPUD = pud_offset(psPGD, ulCPUVAddr);
+    if (pud_none(*psPUD) || pud_bad(*psPUD))
+        return bRet;
+
+    psPMD = pmd_offset(psPUD, ulCPUVAddr);
+    if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+        return bRet;
+
+    psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
+
+    if ((pte_none(*psPTE) == 0) && (pte_present(*psPTE) != 0) && (pte_write(*psPTE) != 0))
+    {
+        *pulPFN = pte_pfn(*psPTE);
+       bRet = IMG_TRUE;
+
+        if (pfn_valid(*pulPFN))
+        {
+            *ppsPage = pfn_to_page(*pulPFN);
+
+            get_page(*ppsPage);
+        }
+    }
+
+    pte_unmap_unlock(psPTE, psPTLock);
+
+    return bRet;
+#else
+    return IMG_FALSE;
+#endif
+}
+
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+    sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
+    IMG_INT i;
+
+    if (psInfo == IMG_NULL)
+    {
+        PVR_DPF((PVR_DBG_WARNING,
+            "OSReleasePhysPageAddr: called with null wrap handle"));
+       return PVRSRV_OK;
+    }
+
+    switch (psInfo->eType)
+    {
+       case WRAP_TYPE_NULL:
+       {
+            PVR_DPF((PVR_DBG_WARNING,
+                "OSReleasePhysPageAddr: called with wrap type WRAP_TYPE_NULL"));
+           break;
+       }
+        case WRAP_TYPE_GET_USER_PAGES:
+        {
+            for (i = 0; i < psInfo->iNumPagesMapped; i++)
+            {
+                struct page *psPage = psInfo->ppsPages[i];
+
+               PVR_ASSERT(psPage != NULL);
+
+
+               if (psInfo->iNumPagesMapped == psInfo->iNumPages)
+               {
+                    if (!PageReserved(psPage))
+                    {
+                        SetPageDirty(psPage);
+                    }
+               }
+                page_cache_release(psPage);
+           }
+            break;
+        }
+        case WRAP_TYPE_FIND_VMA:
+        {
+            for (i = 0; i < psInfo->iNumPages; i++)
+            {
+               if (psInfo->ppsPages[i] != IMG_NULL)
+               {
+                    put_page(psInfo->ppsPages[i]);
+               }
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR,
+                "OSReleasePhysPageAddr: Unknown wrap type (%d)", psInfo->eType));
+            return PVRSRV_ERROR_INVALID_WRAP_TYPE;
+        }
+    }
+
+    if (psInfo->ppsPages != IMG_NULL)
+    {
+        kfree(psInfo->ppsPages);
+    }
+
+    if (psInfo->psPhysAddr != IMG_NULL)
+    {
+        kfree(psInfo->psPhysAddr);
+    }
+
+    kfree(psInfo);
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
+                                    IMG_UINT32 ui32Bytes,
+                                    IMG_SYS_PHYADDR *psSysPAddr,
+                                    IMG_HANDLE *phOSWrapMem)
+{
+    IMG_UINT32 ulStartAddrOrig = (IMG_UINT32) pvCPUVAddr;
+    IMG_UINT32 ulAddrRangeOrig = (IMG_UINT32) ui32Bytes;
+    IMG_UINT32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
+    IMG_UINT32 ulStartAddr;
+    IMG_UINT32 ulAddrRange;
+    IMG_UINT32 ulBeyondEndAddr;
+    IMG_UINT32 ulAddr;
+    IMG_INT i;
+    struct vm_area_struct *psVMArea;
+    sWrapMemInfo *psInfo = NULL;
+    IMG_BOOL bHavePageStructs = IMG_FALSE;
+    IMG_BOOL bHaveNoPageStructs = IMG_FALSE;
+    IMG_BOOL bPFNMismatch = IMG_FALSE;
+    IMG_BOOL bMMapSemHeld = IMG_FALSE;
+    PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+
+    ulStartAddr = ulStartAddrOrig & PAGE_MASK;
+    ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
+    ulAddrRange = ulBeyondEndAddr - ulStartAddr;
+
+
+    if (ulBeyondEndAddr <= ulStartAddr)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Invalid address range (start %x, length %x)",
+               ulStartAddrOrig, ulAddrRangeOrig));
+        goto error;
+    }
+
+
+    psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
+    if (psInfo == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate information structure"));
+        goto error;
+    }
+    memset(psInfo, 0, sizeof(*psInfo));
+
+#if defined(DEBUG)
+    psInfo->ulStartAddr = ulStartAddrOrig;
+    psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+#endif
+
+    psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
+    psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
+
+
+    psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
+    if (psInfo->psPhysAddr == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+        goto error;
+    }
+    memset(psInfo->psPhysAddr, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr));
+
+
+    psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages),  GFP_KERNEL);
+    if (psInfo->ppsPages == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+        goto error;
+    }
+    memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
+
+
+    eError = PVRSRV_ERROR_BAD_MAPPING;
+
+
+    psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+
+    down_read(&current->mm->mmap_sem);
+    bMMapSemHeld = IMG_TRUE;
+
+
+    psInfo->iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+
+    if (psInfo->iNumPagesMapped >= 0)
+    {
+
+        if (psInfo->iNumPagesMapped != psInfo->iNumPages)
+        {
+            PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, psInfo->iNumPagesMapped));
+
+            goto error;
+        }
+
+
+        for (i = 0; i < psInfo->iNumPages; i++)
+        {
+            IMG_CPU_PHYADDR CPUPhysAddr;
+           IMG_UINT32 ulPFN;
+
+            ulPFN = page_to_pfn(psInfo->ppsPages[i]);
+            CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT;
+           if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN)
+           {
+                PVR_DPF((PVR_DBG_ERROR,
+                   "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN));
+
+                   goto error;
+           }
+            psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+            psSysPAddr[i] = psInfo->psPhysAddr[i];
+
+        }
+
+        goto exit;
+    }
+
+    PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), using CPU page table", psInfo->iNumPagesMapped));
+
+
+    psInfo->eType = WRAP_TYPE_NULL;
+    psInfo->iNumPagesMapped = 0;
+    memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
+
+
+
+    psInfo->eType = WRAP_TYPE_FIND_VMA;
+
+    psVMArea = find_vma(current->mm, ulStartAddrOrig);
+    if (psVMArea == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't find memory region containing start address %x", ulStartAddrOrig));
+
+        goto error;
+    }
+#if defined(DEBUG)
+    psInfo->psVMArea = psVMArea;
+#endif
+
+
+    if (ulStartAddrOrig < psVMArea->vm_start)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Start address %x is outside of the region returned by find_vma", ulStartAddrOrig));
+        goto error;
+    }
+
+
+    if (ulBeyondEndAddrOrig > psVMArea->vm_end)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: End address %x is outside of the region returned by find_vma", ulBeyondEndAddrOrig));
+        goto error;
+    }
+
+
+    if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags));
+        goto error;
+    }
+
+
+    if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: No read/write access to memory region (VMA flags: 0x%lx)", psVMArea->vm_flags));
+        goto error;
+    }
+
+    for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+    {
+       IMG_CPU_PHYADDR CPUPhysAddr;
+       IMG_UINT32 ulPFN = 0;
+
+       PVR_ASSERT(i < psInfo->iNumPages);
+
+       if (!CPUVAddrToPFN(psVMArea, ulAddr, &ulPFN, &psInfo->ppsPages[i]))
+       {
+            PVR_DPF((PVR_DBG_ERROR,
+              "OSAcquirePhysPageAddr: Invalid CPU virtual address"));
+
+           goto error;
+       }
+       if (psInfo->ppsPages[i] == NULL)
+       {
+
+           bHaveNoPageStructs = IMG_TRUE;
+
+#if defined(VM_PFNMAP)
+           if ((psVMArea->vm_flags & VM_PFNMAP) != 0)
+           {
+               IMG_UINT32 ulPFNRaw = ((ulAddr - psVMArea->vm_start) >> PAGE_SHIFT) + psVMArea->vm_pgoff;
+
+               if (ulPFNRaw != ulPFN)
+               {
+                       bPFNMismatch = IMG_TRUE;
+               }
+           }
+#endif
+       }
+       else
+       {
+           bHavePageStructs = IMG_TRUE;
+
+           psInfo->iNumPagesMapped++;
+
+           PVR_ASSERT(ulPFN == page_to_pfn(psInfo->ppsPages[i]));
+       }
+
+        CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT;
+       if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN)
+       {
+                PVR_DPF((PVR_DBG_ERROR,
+                   "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN));
+
+                   goto error;
+       }
+
+       psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+       psSysPAddr[i] = psInfo->psPhysAddr[i];
+    }
+    PVR_ASSERT(i ==  psInfo->iNumPages);
+
+#if defined(VM_MIXEDMAP)
+    if ((psVMArea->vm_flags & VM_MIXEDMAP) != 0)
+    {
+        goto exit;
+    }
+#endif
+
+    if (bHavePageStructs && bHaveNoPageStructs)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Region is VM_MIXEDMAP, but isn't marked as such"));
+       goto error;
+    }
+
+    if (!bHaveNoPageStructs)
+    {
+
+       goto exit;
+    }
+
+#if defined(VM_PFNMAP)
+    if ((psVMArea->vm_flags & VM_PFNMAP) == 0)
+#endif
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Region is VM_PFNMAP, but isn't marked as such"));
+       goto error;
+    }
+
+    if (bPFNMismatch)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: PFN calculation mismatch for VM_PFNMAP region"));
+       goto error;
+    }
+
+exit:
+    PVR_ASSERT(bMMapSemHeld);
+    up_read(&current->mm->mmap_sem);
+
+
+    *phOSWrapMem = (IMG_HANDLE)psInfo;
+
+    if (bHaveNoPageStructs)
+    {
+        PVR_DPF((PVR_DBG_WARNING,
+            "OSAcquirePhysPageAddr: Region contains pages which can't be locked down (no page structures)"));
+    }
+
+    PVR_ASSERT(psInfo->eType != 0);
+
+#if 0
+
+
+    OSCleanCPUCacheRangeKM(pvCPUVAddr, (IMG_VOID *)((IMG_CHAR *)pvCPUVAddr + ui32Bytes));
+#endif
+
+    return PVRSRV_OK;
+
+error:
+    if (bMMapSemHeld)
+    {
+        up_read(&current->mm->mmap_sem);
+    }
+    OSReleasePhysPageAddr((IMG_HANDLE)psInfo);
+
+    PVR_ASSERT(eError != PVRSRV_OK);
+
+    return eError;
+}
+
+typedef void (*InnerCacheOp_t)(const void *pvStart, const void *pvEnd);
+typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
+
+#if defined(CONFIG_OUTER_CACHE)
+
+typedef unsigned long (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
+                                                                                IMG_VOID *pvRangeAddrStart,
+                                                                                IMG_UINT32 ui32PageNumOffset,
+                                                                                IMG_UINT32 ui32PageNum);
+
+static unsigned long VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
+                                                                          IMG_VOID *pvRangeAddrStart,
+                                                                          IMG_UINT32 ui32PageNumOffset,
+                                                                          IMG_UINT32 ui32PageNum)
+{
+       return vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+}
+
+static unsigned long ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
+                                                                                 IMG_VOID *pvRangeAddrStart,
+                                                                                 IMG_UINT32 ui32PageNumOffset,
+                                                                                 IMG_UINT32 ui32PageNum)
+{
+       IMG_SYS_PHYADDR SysPAddr;
+       IMG_CPU_PHYADDR CpuPAddr;
+       SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageNumOffset + ui32PageNum];
+       CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+       return CpuPAddr.uiAddr;
+}
+
+static unsigned long AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
+                                                                                 IMG_VOID *pvRangeAddrStart,
+                                                                                 IMG_UINT32 ui32PageNumOffset,
+                                                                                 IMG_UINT32 ui32PageNum)
+{
+       struct page *pPage;
+       pPage = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageNumOffset + ui32PageNum];
+       return page_to_pfn(pPage) << PAGE_SHIFT;
+}
+
+#endif
+
+#ifndef __mips__
+static
+IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
+                                                       IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length)
+{
+       PKV_OFFSET_STRUCT psOffsetStruct;
+       IMG_VOID *pvMinVAddr;
+
+
+       list_for_each_entry(psOffsetStruct, psMMapOffsetStructList, sAreaItem)
+       {
+               if(OSGetCurrentProcessIDKM() != psOffsetStruct->ui32PID)
+                       continue;
+
+               pvMinVAddr = (IMG_VOID *)psOffsetStruct->ui32UserVAddr;
+
+
+               if(pvRangeAddrStart >= pvMinVAddr &&
+                  ui32Length <= psOffsetStruct->ui32RealByteSize)
+                       return pvMinVAddr;
+       }
+
+       return IMG_NULL;
+}
+
+static
+IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
+                                                        IMG_VOID *pvRangeAddrStart,
+                                                        IMG_UINT32 ui32Length,
+                                                        InnerCacheOp_t pfnInnerCacheOp,
+                                                        OuterCacheOp_t pfnOuterCacheOp)
+{
+       LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+       IMG_UINT32 ui32AreaLength, ui32AreaOffset = 0;
+       struct list_head *psMMapOffsetStructList;
+       IMG_VOID *pvMinVAddr;
+
+#if defined(CONFIG_OUTER_CACHE)
+       MemAreaToPhys_t pfnMemAreaToPhys = IMG_NULL;
+       IMG_UINT32 ui32PageNumOffset = 0;
+#endif
+
+       PVR_ASSERT(psLinuxMemArea != IMG_NULL);
+
+       ui32AreaLength = psLinuxMemArea->ui32ByteSize;
+       psMMapOffsetStructList = &psLinuxMemArea->sMMapOffsetStructList;
+
+       PVR_ASSERT(ui32Length <= ui32AreaLength);
+
+       if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+       {
+               ui32AreaOffset = psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+               psLinuxMemArea = psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+       }
+
+
+       PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+       switch(psLinuxMemArea->eAreaType)
+       {
+               case LINUX_MEM_AREA_VMALLOC:
+               {
+                       if(is_vmalloc_addr(pvRangeAddrStart))
+                       {
+                       pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset;
+
+
+                               if(pvRangeAddrStart < pvMinVAddr)
+                               goto err_blocked;
+
+                               pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+               }
+               else
+               {
+
+
+
+                       pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+                                                                                  pvRangeAddrStart, ui32Length);
+                       if(!pvMinVAddr)
+                               goto err_blocked;
+
+                       pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+
+                               pvRangeAddrStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
+                                                                  (ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr);
+                       }
+
+                       pfnMemAreaToPhys = VMallocAreaToPhys;
+#else
+                       }
+#endif
+                       break;
+               }
+
+               case LINUX_MEM_AREA_EXTERNAL_KV:
+               {
+
+                       if (psLinuxMemArea->uData.sExternalKV.bPhysContig == IMG_TRUE)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush contiguous external memory", __func__));
+
+                               goto err_blocked;
+                       }
+
+
+                       if (psLinuxMemArea->uData.sExternalKV.pvExternalKV != IMG_NULL)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush external memory with a kernel virtual address", __func__));
+
+                               goto err_blocked;
+                       }
+
+
+
+                       pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+                                                                                  pvRangeAddrStart, ui32Length);
+                       if(!pvMinVAddr)
+                               goto err_blocked;
+
+                       pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+                       ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+                       pfnMemAreaToPhys = ExternalKVAreaToPhys;
+#endif
+                       break;
+               }
+
+               case LINUX_MEM_AREA_ALLOC_PAGES:
+               {
+                       pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+                                                                                  pvRangeAddrStart, ui32Length);
+                       if(!pvMinVAddr)
+                               goto err_blocked;
+
+                       pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+                       ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+                       pfnMemAreaToPhys = AllocPagesAreaToPhys;
+#endif
+                       break;
+               }
+
+               default:
+                       PVR_DBG_BREAK;
+       }
+
+#if defined(CONFIG_OUTER_CACHE)
+       PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
+
+
+       {
+               unsigned long ulStart, ulEnd, ulLength, ulStartOffset, ulEndOffset;
+               IMG_UINT32 i, ui32NumPages;
+
+
+               ulLength = (unsigned long)ui32Length;
+               ulStartOffset = ((unsigned long)pvRangeAddrStart) & (PAGE_SIZE - 1);
+               ulEndOffset = ((unsigned long)pvRangeAddrStart + ulLength) & (PAGE_SIZE - 1);
+
+
+               ui32NumPages = (ulStartOffset + ulLength + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+               for(i = 0; i < ui32NumPages; i++)
+               {
+                       ulStart = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
+                                                                          ui32PageNumOffset, i);
+                       ulEnd = ulStart + PAGE_SIZE;
+
+                       if(i == ui32NumPages - 1 && ulEndOffset != 0)
+                               ulEnd = ulStart + ulEndOffset;
+
+                       if(i == 0)
+                               ulStart += ulStartOffset;
+
+                       pfnOuterCacheOp(ulStart, ulEnd);
+               }
+       }
+#endif
+
+       return IMG_TRUE;
+
+err_blocked:
+       PVR_DPF((PVR_DBG_WARNING, "%s: Blocked cache op on virtual range "
+                                                         "%p-%p (type %d)", __func__,
+                        pvRangeAddrStart, pvRangeAddrStart + ui32Length,
+                        psLinuxMemArea->eAreaType));
+       return IMG_FALSE;
+}
+
+#endif
+
+#if defined(__i386__)
+
+#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1))
+
+static void per_cpu_cache_flush(void *arg)
+{
+    PVR_UNREFERENCED_PARAMETER(arg);
+    wbinvd();
+}
+
+static void x86_flush_cache_range(const void *pvStart, const void *pvEnd)
+{
+       IMG_BYTE *pbStart = (IMG_BYTE *)pvStart;
+       IMG_BYTE *pbEnd = (IMG_BYTE *)pvEnd;
+       IMG_BYTE *pbBase;
+
+       pbEnd = (IMG_BYTE *)ROUND_UP((IMG_UINTPTR_T)pbEnd,
+                                                                boot_cpu_data.x86_clflush_size);
+
+       mb();
+       for(pbBase = pbStart; pbBase < pbEnd; pbBase += boot_cpu_data.x86_clflush_size)
+               clflush(pbBase);
+       mb();
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+
+       ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+       ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                               IMG_VOID *pvRangeAddrStart,
+                                                               IMG_UINT32 ui32Length)
+{
+
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+                                                          x86_flush_cache_range, IMG_NULL);
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                               IMG_VOID *pvRangeAddrStart,
+                                                               IMG_UINT32 ui32Length)
+{
+
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+                                                          x86_flush_cache_range, IMG_NULL);
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                                        IMG_VOID *pvRangeAddrStart,
+                                                                        IMG_UINT32 ui32Length)
+{
+
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+                                                          x86_flush_cache_range, IMG_NULL);
+}
+
+#else
+
+#if defined(__arm__)
+
+static void per_cpu_cache_flush(void *arg)
+{
+       PVR_UNREFERENCED_PARAMETER(arg);
+       flush_cache_all();
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+
+       ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
+       outer_clean_all();
+#endif
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+       ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
+       outer_flush_all();
+#endif
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                               IMG_VOID *pvRangeAddrStart,
+                                                               IMG_UINT32 ui32Length)
+{
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+                                                          dmac_flush_range, outer_flush_range);
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                               IMG_VOID *pvRangeAddrStart,
+                                                               IMG_UINT32 ui32Length)
+{
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+                                                          dmac_clean_range, outer_clean_range);
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                                        IMG_VOID *pvRangeAddrStart,
+                                                                        IMG_UINT32 ui32Length)
+{
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+                                                          dmac_inv_range, outer_inv_range);
+}
+
+#else
+
+#error "Implement CPU cache flush/clean/invalidate primitives for this CPU!"
+
+#endif
+
+#endif
+
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    {
+        psTimerWorkQueue = create_workqueue("pvr_timer");
+        if (psTimerWorkQueue == NULL)
+        {
+           PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));
+           return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+
+        }
+    }
+#endif
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    {
+       IMG_UINT32 ui32i;
+
+        for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+        {
+            TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i];
+
+           INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack);
+        }
+    }
+#endif
+    return PVRSRV_OK;
+}
+
+IMG_VOID PVROSFuncDeInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    if (psTimerWorkQueue != NULL)
+    {
+       destroy_workqueue(psTimerWorkQueue);
+    }
+#endif
+}
+#ifdef PVRSRV_OS_MEM_INFO
+IMG_VOID OSGetMemoryInfo(PVRSRV_MEM_INFO * psMemInfo)
+{
+       struct sysinfo si;
+       long cached;
+       si_meminfo(&si);
+       cached = global_page_state(NR_FILE_PAGES);
+       psMemInfo->ui32FreeMem = (cached + si.freeram) << PAGE_SHIFT;
+       psMemInfo->ui32TotalMem = si.totalram;
+}
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/osperproc.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/osperproc.c
new file mode 100644 (file)
index 0000000..011c8f3
--- /dev/null
@@ -0,0 +1,113 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+#include "proc.h"
+
+extern IMG_UINT32 gui32ReleasePID;
+
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hBlockAlloc;
+       PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                               sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+                               phOsPrivateData,
+                               &hBlockAlloc,
+                               "Environment per Process Data");
+
+       if (eError != PVRSRV_OK)
+       {
+               *phOsPrivateData = IMG_NULL;
+
+               PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError));
+               return eError;
+       }
+
+       psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+       OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+       psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+       
+       LinuxMMapPerProcessConnect(psEnvPerProc);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       
+       INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
+#endif
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+       if (hOsPrivateData == IMG_NULL)
+       {
+               return PVRSRV_OK;
+       }
+
+       psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+       
+       LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+       
+       RemovePerProcessProcDir(psEnvPerProc);
+
+       eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                               sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+                               hOsPrivateData,
+                               psEnvPerProc->hBlockAlloc);
+       
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError));
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+       return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID)
+{
+       if(!gui32ReleasePID)
+               return NULL;
+       return PVRSRVPerProcessPrivateData(gui32ReleasePID);
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/ossync.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/ossync.c
new file mode 100644 (file)
index 0000000..576d5b6
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,·
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+ * Pauli Nieminen <pauli.nieminen@intel.com>
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#include "ossync.h"
+#include "servicesint.h"
+
+DEFINE_SPINLOCK(sync_lock);
+LIST_HEAD(sync_list);
+
+typedef void (*callback_t)(void *);
+
+struct pending_sync {
+       PVRSRV_KERNEL_SYNC_INFO *sync_info;
+       int pending_read_ops;
+       int pending_write_ops;
+       int flags;
+       callback_t callback;
+       void *user_data;
+
+       struct list_head list;
+};
+
+/* Returns 0 if the callback was successfully registered.
+ * Returns a negative value on error.
+ */
+int
+PVRSRVCallbackOnSync(PVRSRV_KERNEL_SYNC_INFO *sync_info, int flags,
+                     callback_t callback, void *user_data)
+{
+       struct pending_sync *pending_sync;
+       unsigned long lock_flags;
+
+       /* If the object is already in sync, don't add it to the list */
+       if ((!(flags & PVRSRV_SYNC_READ)
+            || (sync_info->psSyncData->ui32ReadOpsPending
+                <= sync_info->psSyncData->ui32ReadOpsComplete))
+           && (!(flags & PVRSRV_SYNC_WRITE)
+               || (sync_info->psSyncData->ui32WriteOpsPending
+                   <= sync_info->psSyncData->ui32WriteOpsComplete))) {
+               callback(user_data);
+               return 0;
+       }
+
+       pending_sync = kmalloc(sizeof *pending_sync, GFP_KERNEL);
+       if (!pending_sync)
+               return -ENOMEM;
+
+       pending_sync->sync_info = sync_info;
+       pending_sync->pending_read_ops = sync_info->psSyncData->ui32ReadOpsPending;
+       pending_sync->pending_write_ops = sync_info->psSyncData->ui32WriteOpsPending;
+       pending_sync->flags = flags;
+       pending_sync->callback = callback;
+       pending_sync->user_data = user_data;
+
+       spin_lock_irqsave(&sync_lock, lock_flags);
+       list_add_tail(&pending_sync->list, &sync_list);
+       spin_unlock_irqrestore(&sync_lock, lock_flags);
+
+       return 0;
+}
+
+void
+PVRSRVCheckPendingSyncs()
+{
+       struct pending_sync *ps, *tmp;
+       int read_ops_done, write_ops_done;
+       int sync_read, sync_write;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sync_lock, flags);
+
+       list_for_each_entry_safe(ps, tmp, &sync_list, list) {
+               sync_read = (ps->flags & PVRSRV_SYNC_READ) != 0;
+               read_ops_done = ps->sync_info->psSyncData->ui32ReadOpsComplete;
+
+               sync_write = (ps->flags & PVRSRV_SYNC_WRITE) != 0;
+               write_ops_done = ps->sync_info->psSyncData->ui32WriteOpsComplete;
+
+               if ((!sync_read || ps->pending_read_ops <= read_ops_done)
+                   && (!sync_write || ps->pending_write_ops <= write_ops_done)) {
+                       ps->callback(ps->user_data);
+                       list_del(&ps->list);
+                       kfree(ps);
+               }
+       }
+
+       spin_unlock_irqrestore(&sync_lock, flags);
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pdump.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pdump.c
new file mode 100644 (file)
index 0000000..0b932b0
--- /dev/null
@@ -0,0 +1,628 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if defined (SUPPORT_SGX) || defined (SUPPORT_VGX)
+#if defined (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+#if defined (SUPPORT_SGX)
+#include "sgxdefs.h" 
+#endif
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#if defined (SUPPORT_SGX)
+#include "sgxmmu.h"
+#endif
+#include "mm.h"
+#include "pdump_km.h"
+#include "pdump_int.h"
+
+#include <linux/kernel.h> 
+#include <linux/string.h> 
+
+static IMG_BOOL PDumpWriteString2              (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
+static IMG_BOOL PDumpWriteILock                        (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
+static IMG_VOID DbgSetFrame                            (PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
+static IMG_VOID DbgSetMarker                   (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+
+#define PDUMP_DATAMASTER_PIXEL         (1)
+#define PDUMP_DATAMASTER_EDM           (3)
+
+#define MAX_FILE_SIZE  0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
+                                                                                               "ScriptStream2",
+                                                                                               "DriverInfoStream"};
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+       PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
+       IMG_UINT32 ui32ParamFileNum;
+
+       IMG_CHAR *pszMsg;
+       IMG_CHAR *pszScript;
+       IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX                        PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX             PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX   PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+
+
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+static inline IMG_BOOL PDumpSuspended(IMG_VOID)
+{
+       return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+                                                                       IMG_UINT32 *pui32MaxLen)
+{
+       *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+       *pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+       if ((!*phScript) || PDumpSuspended())
+       {
+               return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg,
+                                                                        IMG_UINT32 *pui32MaxLen)
+{
+       *ppszMsg = gsDBGPdumpState.pszMsg;
+       *pui32MaxLen = SZ_MSG_SIZE_MAX;
+       if ((!*ppszMsg) || PDumpSuspended())
+       {
+               return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+                                                                        IMG_UINT32 *pui32MaxLen)
+{
+       *ppszFile = gsDBGPdumpState.pszFile;
+       *pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+       if ((!*ppszFile) || PDumpSuspended())
+       {
+               return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+       }
+       return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
+{
+       return PDumpWriteString2(hScript, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+       IMG_CHAR* pszBuf = hBuf;
+       IMG_INT32 n;
+       va_list vaArgs;
+
+       va_start(vaArgs, pszFormat);
+
+       n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+       va_end(vaArgs);
+
+       if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)   
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+               return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+       }
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+       g_ui32EveryLineCounter++;
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+       IMG_INT32 n;
+
+       n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+       if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)   
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+               return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+       }
+
+       return PVRSRV_OK;
+}
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+       PVR_UNREFERENCED_PARAMETER(pszFormat);
+
+       
+}
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+       IMG_INT32 n;
+       va_list vaArgs;
+
+       va_start(vaArgs, pszFormat);
+
+       n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+       va_end(vaArgs);
+
+       if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)   
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+               return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+       }
+
+       return PVRSRV_OK;
+}
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+       IMG_CHAR* pszBuf = hBuffer;
+       IMG_UINT32 ui32Count = 0;
+
+       while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+       {
+               ui32Count++;
+       }
+       return(ui32Count);
+}
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+       IMG_UINT32 ui32Count;
+       IMG_CHAR* pszBuf = hBuffer;
+
+       
+       ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+       
+       if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+       {
+               pszBuf[ui32Count] = '\n';
+               ui32Count++;
+               pszBuf[ui32Count] = '\0';
+       }
+       if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
+       {
+               pszBuf[ui32Count-1] = '\r';
+               pszBuf[ui32Count] = '\n';
+               ui32Count++;
+               pszBuf[ui32Count] = '\0';
+       }
+}
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
+{
+       return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
+}
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
+{
+       PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
+       return gpfnDbgDrv->pfnGetStreamOffset(psStream);
+}
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
+{
+       return gsDBGPdumpState.ui32ParamFileNum;
+}
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
+               IMG_UINT8 *psui8Data,
+               IMG_UINT32 ui32Size,
+               IMG_UINT32 ui32Flags)
+{
+       PDBG_STREAM psStream = (PDBG_STREAM)hStream;
+       return PDumpWriteILock(psStream,
+                                       psui8Data,
+                                       ui32Size,
+                                       ui32Flags);
+}
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+{
+       
+       PVR_UNREFERENCED_PARAMETER(hStream);
+       PVR_UNREFERENCED_PARAMETER(ui32Size);
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+}
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
+{
+       if(gpfnDbgDrv)
+       {
+               return IMG_TRUE;
+       }
+       return IMG_FALSE;
+}
+
+inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
+{
+       return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+        IMG_HANDLE hOSMemHandle,
+               IMG_UINT32 ui32Offset,
+               IMG_UINT8 *pui8LinAddr,
+               IMG_UINT32 ui32PageSize,
+               IMG_DEV_PHYADDR *psDevPAddr)
+{
+       IMG_CPU_PHYADDR sCpuPAddr;
+
+       PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+       PVR_UNREFERENCED_PARAMETER(ui32PageSize);   
+
+       
+          
+       PVR_ASSERT (hOSMemHandle != IMG_NULL);
+       
+       sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+       PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+
+       
+       *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+}
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+               IMG_UINT32 ui32Offset,
+               IMG_PUINT8 pui8LinAddr,
+               IMG_UINT32 ui32DataPageMask,
+               IMG_UINT32 *pui32PageOffset)
+{
+       if(hOSMemHandle)
+       {
+               
+               IMG_CPU_PHYADDR     sCpuPAddr;
+
+               PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+               sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+           *pui32PageOffset = sCpuPAddr.uiAddr & ui32DataPageMask;
+       }
+       else
+       {
+               PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+               PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+               *pui32PageOffset = ((IMG_UINT32)pui8LinAddr & ui32DataPageMask);
+       }
+}
+
+IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
+                                                                       PDUMP_DDWMODE eDbgDrvWriteMode,
+                                                                       IMG_UINT8 *pui8Data,
+                                                                       IMG_UINT32 ui32BCount,
+                                                                       IMG_UINT32 ui32Level,
+                                                                       IMG_UINT32 ui32DbgDrvFlags)
+{
+       switch(eDbgDrvWriteMode)
+       {
+               case PDUMP_WRITE_MODE_CONTINUOUS:
+                       PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+                       return gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, ui32Level);
+               case PDUMP_WRITE_MODE_LASTFRAME:
+                       return gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, ui32Level, ui32DbgDrvFlags);
+               case PDUMP_WRITE_MODE_BINCM:
+                       PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+                       return gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, ui32Level);
+               case PDUMP_WRITE_MODE_PERSISTENT:
+                       PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+                       return gpfnDbgDrv->pfnWritePersist(psStream, pui8Data, ui32BCount, ui32Level);
+               default:
+                       PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+                       break;
+       }
+       return 0xFFFFFFFFU;
+}
+
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID)
+{
+       OSReleaseThreadQuanta();
+}
+
+IMG_VOID PDumpInit(IMG_VOID)
+{
+       IMG_UINT32 i;
+       DBGKM_CONNECT_NOTIFIER sConnectNotifier;
+
+       
+       if (!gpfnDbgDrv)
+       {
+               DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+
+
+               
+               if (gpfnDbgDrv == IMG_NULL)
+               {
+                       return;
+               }
+               
+               
+               sConnectNotifier.pfnConnectNotifier = &PDumpConnectionNotify;
+               gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+               if(!gsDBGPdumpState.pszFile)
+               {
+                       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
+                               "Filename string") != PVRSRV_OK)
+                       {
+                               goto init_failed;
+                       }
+               }
+
+               if(!gsDBGPdumpState.pszMsg)
+               {
+                       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
+                               "Message string") != PVRSRV_OK)
+                       {
+                               goto init_failed;
+                       }
+               }
+
+               if(!gsDBGPdumpState.pszScript)
+               {
+                       if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
+                               "Script string") != PVRSRV_OK)
+                       {
+                               goto init_failed;
+                       }
+               }
+
+               for(i=0; i < PDUMP_NUM_STREAMS; i++)
+               {
+                       gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+                                                                                                               DEBUG_CAPMODE_FRAMED,
+                                                                                                               DEBUG_OUTMODE_STREAMENABLE,
+                                                                                                               0,
+                                                                                                               10);
+
+                       gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
+                       gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
+               }
+
+               PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+               PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FILE);
+               PDUMPCOMMENT("Start of Init Phase");
+       }
+
+       return;
+
+init_failed:
+
+       if(gsDBGPdumpState.pszFile)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+               gsDBGPdumpState.pszFile = IMG_NULL;
+       }
+
+       if(gsDBGPdumpState.pszScript)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+               gsDBGPdumpState.pszScript = IMG_NULL;
+       }
+
+       if(gsDBGPdumpState.pszMsg)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+               gsDBGPdumpState.pszMsg = IMG_NULL;
+       }
+
+       
+       sConnectNotifier.pfnConnectNotifier = 0;
+       gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+       gpfnDbgDrv = IMG_NULL;
+}
+
+
+IMG_VOID PDumpDeInit(IMG_VOID)
+{
+       IMG_UINT32 i;
+       DBGKM_CONNECT_NOTIFIER sConnectNotifier;
+
+       for(i=0; i < PDUMP_NUM_STREAMS; i++)
+       {
+               gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+       }
+
+       if(gsDBGPdumpState.pszFile)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+               gsDBGPdumpState.pszFile = IMG_NULL;
+       }
+
+       if(gsDBGPdumpState.pszScript)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+               gsDBGPdumpState.pszScript = IMG_NULL;
+       }
+
+       if(gsDBGPdumpState.pszMsg)
+       {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+               gsDBGPdumpState.pszMsg = IMG_NULL;
+       }
+
+       
+       sConnectNotifier.pfnConnectNotifier = 0;
+       gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+       gpfnDbgDrv = IMG_NULL;
+}
+
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       if (gpfnDbgDrv)
+       {
+               PDUMPCOMMENT("Start Init Phase");
+               for(i=0; i < PDUMP_NUM_STREAMS; i++)
+               {
+                       gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
+               }
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       if (gpfnDbgDrv)
+       {
+               PDUMPCOMMENT("Stop Init Phase");
+
+               for(i=0; i < PDUMP_NUM_STREAMS; i++)
+               {
+                       gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
+               }
+       }
+       return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+       return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+
+IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID)
+{
+       if (PDumpSuspended())
+       {
+               return IMG_FALSE;
+       }
+       return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
+}
+
+PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame)
+{
+       IMG_UINT32      ui32Stream;
+
+       for     (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+       {
+               if      (gsDBGPdumpState.psStream[ui32Stream])
+               {
+                       DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+       return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
+}
+
+
+static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
+{
+       IMG_UINT32 ui32Written = 0;
+       if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "PDumpWriteILock: Failed to write 0x%x bytes to stream 0x%x", ui32Count, (IMG_UINT32)psStream));
+               return IMG_TRUE;
+       }
+
+
+       
+
+       if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
+       {
+               IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
+
+               if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+               {
+                       if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
+                       {
+                               DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
+                               gsDBGPdumpState.ui32ParamFileNum++;
+                       }
+               }
+       }
+
+       ui32Written = DbgWrite(psStream, pui8Data, ui32Count, ui32Flags);
+
+       if (ui32Written == 0xFFFFFFFF)
+       {
+               return IMG_FALSE;
+       }
+
+       return IMG_TRUE;
+}
+
+static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+       gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+       gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+       atomic_inc(&gsPDumpSuspended);
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+       atomic_dec(&gsPDumpSuspended);
+}
+
+#endif 
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/private_data.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/private_data.h
new file mode 100644 (file)
index 0000000..a011d66
--- /dev/null
@@ -0,0 +1,74 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include <linux/list.h>
+#include <drm/drmP.h>
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+typedef struct
+{
+       
+       IMG_UINT32 ui32OpenPID;
+
+       IMG_HANDLE sec_fd_exp_meminfo;
+
+#if defined(SUPPORT_DRI_DRM)
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       struct drm_file *psDRMFile;
+
+       
+       struct list_head sDRMAuthListItem;
+#endif
+
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+       struct work_struct sReleaseWork;
+#endif
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+       IMG_PVOID pPriv;        
+#endif
+#endif 
+
+#if defined(SUPPORT_MEMINFO_IDS)
+       
+       IMG_UINT64 ui64Stamp;
+#endif 
+
+       
+       IMG_HANDLE hBlockAlloc;
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/proc.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/proc.c
new file mode 100644 (file)
index 0000000..0cea222
--- /dev/null
@@ -0,0 +1,828 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "linkage.h"
+
+#include "lists.h"
+
+static struct proc_dir_entry * dir;
+
+static const IMG_CHAR PVRProcDirRoot[] = "pvr";
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
+
+static struct file_operations pvr_proc_operations =
+{
+       .open           = pvr_proc_open,
+       .read           = seq_read,
+       .write          = pvr_proc_write,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static struct seq_operations pvr_proc_seq_operations =
+{
+       .start =        pvr_proc_seq_start,
+       .next =         pvr_proc_seq_next,
+       .stop =         pvr_proc_seq_stop,
+       .show =         pvr_proc_seq_show,
+};
+
+static struct proc_dir_entry* g_pProcQueue;
+static struct proc_dir_entry* g_pProcVersion;
+static struct proc_dir_entry* g_pProcSysNodes;
+
+#ifdef DEBUG
+static struct proc_dir_entry* g_pProcDebugLevel;
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+static struct proc_dir_entry* g_pProcPowerLevel;
+#endif
+
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+{
+    IMG_INT n;
+    size_t space = size - (size_t)off;
+    va_list ap;
+
+    va_start (ap, format);
+
+    n = vsnprintf (buffer+off, space, format, ap);
+
+    va_end (ap);
+    
+    if (n >= (IMG_INT)space || n < 0)
+    {
+       
+        buffer[size - 1] = 0;
+        return (off_t)(size - 1);
+    }
+    else
+    {
+        return (off + (off_t)n);
+    }
+}
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+{
+       PVR_UNREFERENCED_PARAMETER(sfile);
+       
+       if(!off)
+               return (void*)2;
+       return NULL;
+}
+
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+{
+       PVR_UNREFERENCED_PARAMETER(sfile);
+
+       if(!off)
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+       
+       if(off == 1)
+               return (void*)2;
+
+       return NULL;
+}
+
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
+{
+       IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
+
+       struct seq_file *seq = (struct seq_file*)file->private_data;
+       struct proc_dir_entry* pvr_proc_entry = PDE(inode);
+
+       
+       seq->private = pvr_proc_entry->data;
+       return ret;
+}
+
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t *ppos)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct proc_dir_entry * dp;
+
+       PVR_UNREFERENCED_PARAMETER(ppos);
+       dp = PDE(inode);
+
+       if (!dp->write_proc)
+               return -EIO;
+
+       return dp->write_proc(file, buffer, count, dp->data);
+}
+
+
+static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+       if(handlers->startstop != NULL)
+               handlers->startstop(proc_seq_file, IMG_TRUE);
+       return handlers->off2element(proc_seq_file, *pos);
+}
+
+static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+       PVR_UNREFERENCED_PARAMETER(v);
+
+       if(handlers->startstop != NULL)
+               handlers->startstop(proc_seq_file, IMG_FALSE);
+}
+
+static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+       (*pos)++;
+       if( handlers->next != NULL)
+               return handlers->next( proc_seq_file, v, *pos );
+       return handlers->off2element(proc_seq_file, *pos);
+}
+
+static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+{
+       PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+       handlers->show( proc_seq_file,v );
+    return 0;
+}
+
+
+
+static struct proc_dir_entry* CreateProcEntryInDirSeq(
+                                                                          struct proc_dir_entry *pdir,
+                                                                          const IMG_CHAR * name,
+                                                                  IMG_VOID* data,
+                                                                          pvr_next_proc_seq_t next_handler,
+                                                                          pvr_show_proc_seq_t show_handler,
+                                                                          pvr_off2element_proc_seq_t off2element_handler,
+                                                                          pvr_startstop_proc_seq_t startstop_handler,
+                                                                          write_proc_t whandler
+                                                                          )
+{
+
+    struct proc_dir_entry * file;
+       mode_t mode;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+        return NULL;
+    }
+
+       mode = S_IFREG;
+
+    if (show_handler)
+    {
+               mode |= S_IRUGO;
+    }
+
+    if (whandler)
+    {
+               mode |= S_IWUSR;
+    }
+
+       file=create_proc_entry(name, mode, pdir);
+
+    if (file)
+    {
+               PVR_PROC_SEQ_HANDLERS *seq_handlers;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+        file->owner = THIS_MODULE;
+#endif
+
+               file->proc_fops = &pvr_proc_operations;
+               file->write_proc = whandler;
+
+               
+               file->data =  kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
+               if(file->data)
+               {
+                       seq_handlers = (PVR_PROC_SEQ_HANDLERS*)file->data;
+                       seq_handlers->next = next_handler;
+                       seq_handlers->show = show_handler;
+                       seq_handlers->off2element = off2element_handler;
+                       seq_handlers->startstop = startstop_handler;
+                       seq_handlers->data = data;
+
+               return file;
+               }
+    }
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+    return NULL;
+}
+
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+                                                               const IMG_CHAR * name,
+                                                               IMG_VOID* data,
+                                                               pvr_next_proc_seq_t next_handler,
+                                                               pvr_show_proc_seq_t show_handler,
+                                                               pvr_off2element_proc_seq_t off2element_handler,
+                                                               pvr_startstop_proc_seq_t startstop_handler
+                                                          )
+{
+       return CreateProcEntrySeq(name,
+                                                         data,
+                                                         next_handler,
+                                                         show_handler,
+                                                         off2element_handler,
+                                                         startstop_handler,
+                                                         NULL);
+}
+
+struct proc_dir_entry* CreateProcEntrySeq (
+                                                                                       const IMG_CHAR * name,
+                                                                                       IMG_VOID* data,
+                                                                                       pvr_next_proc_seq_t next_handler,
+                                                                                       pvr_show_proc_seq_t show_handler,
+                                                                                       pvr_off2element_proc_seq_t off2element_handler,
+                                                                                       pvr_startstop_proc_seq_t startstop_handler,
+                                                                                       write_proc_t whandler
+                                                                                 )
+{
+       return CreateProcEntryInDirSeq(
+                                                                  dir,
+                                                                  name,
+                                                                  data,
+                                                                  next_handler,
+                                                                  show_handler,
+                                                                  off2element_handler,
+                                                                  startstop_handler,
+                                                                  whandler
+                                                                 );
+}
+
+
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+                                                                         const IMG_CHAR * name,
+                                                                 IMG_VOID* data,
+                                                                         pvr_next_proc_seq_t next_handler,
+                                                                         pvr_show_proc_seq_t show_handler,
+                                                                         pvr_off2element_proc_seq_t off2element_handler,
+                                                                         pvr_startstop_proc_seq_t startstop_handler,
+                                                                         write_proc_t whandler
+                                                                        )
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+    IMG_UINT32 ui32PID;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
+        return NULL;
+    }
+
+    ui32PID = OSGetCurrentProcessIDKM();
+
+    psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+    if (!psPerProc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
+
+        return NULL;
+    }
+
+    if (!psPerProc->psProcDir)
+    {
+        IMG_CHAR dirname[16];
+        IMG_INT ret;
+
+        ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+
+               if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+                       return NULL;
+               }
+               else
+               {
+                       psPerProc->psProcDir = proc_mkdir(dirname, dir);
+                       if (!psPerProc->psProcDir)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
+                                               PVRProcDirRoot, ui32PID));
+                               return NULL;
+                       }
+               }
+    }
+
+    return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+                                                                  show_handler,off2element_handler,startstop_handler,whandler);
+}
+
+
+IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
+{
+    if (dir)
+    {
+               void* data = proc_entry->data ;
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, proc_entry->name));
+
+        remove_proc_entry(proc_entry->name, dir);
+               if( data)
+                       kfree( data );
+
+    }
+}
+
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+    psPerProc = LinuxTerminatingProcessPrivateData();
+    if (!psPerProc)
+    {
+        psPerProc = PVRSRVFindPerProcessPrivateData();
+        if (!psPerProc)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+                                    "remove %s, no per process data", proc_entry->name));
+            return;
+        }
+    }
+
+    if (psPerProc->psProcDir)
+    {
+               void* data = proc_entry->data ;
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", proc_entry->name, psPerProc->psProcDir->name));
+
+        remove_proc_entry(proc_entry->name, psPerProc->psProcDir);
+               if(data)
+                       kfree( data );
+    }
+}
+
+static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
+                         IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+        
+    pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
+
+    off_t len = pprn (page, (size_t)count, off);
+
+    if (len == END_OF_FILE)
+    {
+        len  = 0;
+        *eof = 1;
+    }
+    else if (!len)             
+    {
+        *start = (IMG_CHAR *) 0;   
+    }
+    else
+    {
+        *start = (IMG_CHAR *) 1;
+    }
+
+    return len;
+}
+
+
+static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    struct proc_dir_entry * file;
+    mode_t mode;
+
+    if (!pdir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDir: parent directory doesn't exist"));
+
+        return -ENOMEM;
+    }
+
+    mode = S_IFREG;
+
+    if (rhandler)
+    {
+       mode |= S_IRUGO;
+    }
+
+    if (whandler)
+    {
+       mode |= S_IWUSR;
+    }
+
+    file = create_proc_entry(name, mode, pdir);
+
+    if (file)
+    {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+        file->owner = THIS_MODULE;
+#endif
+               file->read_proc = rhandler;
+               file->write_proc = whandler;
+               file->data = data;
+
+               PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, pdir->name));
+
+        return 0;
+    }
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, pdir->name));
+
+    return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+    IMG_UINT32 ui32PID;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: /proc/%s doesn't exist", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+    ui32PID = OSGetCurrentProcessIDKM();
+
+    psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+    if (!psPerProc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: no per process data"));
+
+        return -ENOMEM;
+    }
+
+    if (!psPerProc->psProcDir)
+    {
+        IMG_CHAR dirname[16];
+        IMG_INT ret;
+
+        ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+
+               if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+
+                                       return -ENOMEM;
+               }
+               else
+               {
+                       psPerProc->psProcDir = proc_mkdir(dirname, dir);
+                       if (!psPerProc->psProcDir)
+                       {
+                       PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u", PVRProcDirRoot, ui32PID));
+
+                       return -ENOMEM;
+                       }
+               }
+    }
+
+    return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
+{
+    struct proc_dir_entry * file;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+
+        return -ENOMEM;
+    }
+
+        
+    file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
+
+    if (file)
+    {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+        file->owner = THIS_MODULE;
+#endif
+        return 0;
+    }
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+
+    return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntries(IMG_VOID)
+{
+    dir = proc_mkdir (PVRProcDirRoot, NULL);
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+       g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+       g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
+       g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
+
+       if(!g_pProcQueue || !g_pProcVersion || !g_pProcSysNodes)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+
+#ifdef DEBUG
+
+       g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
+                                                                                       ProcSeqShowDebugLevel,
+                                                                                       ProcSeq1ElementOff2Element, NULL,
+                                                                                   (IMG_VOID*)PVRDebugProcSetLevel);
+       if(!g_pProcDebugLevel)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+       g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
+                                                                                       ProcSeqShowPowerLevel,
+                                                                                       ProcSeq1ElementOff2Element, NULL,
+                                                                                   PVRProcSetPowerLevel);
+       if(!g_pProcPowerLevel)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+#endif
+#endif
+
+    return 0;
+}
+
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+    if (dir)
+    {
+        remove_proc_entry(name, dir);
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
+    }
+}
+
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+    psPerProc = LinuxTerminatingProcessPrivateData();
+    if (!psPerProc)
+    {
+        psPerProc = PVRSRVFindPerProcessPrivateData();
+        if (!psPerProc)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+                                    "remove %s, no per process data", name));
+            return;
+        }
+    }
+
+    if (psPerProc->psProcDir)
+    {
+        remove_proc_entry(name, psPerProc->psProcDir);
+
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name));
+    }
+}
+
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+    if (psPerProc->psProcDir)
+    {
+        while (psPerProc->psProcDir->subdir)
+        {
+            PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
+
+            RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+        }
+        RemoveProcEntry(psPerProc->psProcDir->name);
+    }
+}
+
+IMG_VOID RemoveProcEntries(IMG_VOID)
+{
+#ifdef DEBUG
+       RemoveProcEntrySeq( g_pProcDebugLevel );
+#ifdef PVR_MANUAL_POWER_CONTROL
+       RemoveProcEntrySeq( g_pProcPowerLevel );
+#endif 
+#endif
+
+       RemoveProcEntrySeq(g_pProcQueue);
+       RemoveProcEntrySeq(g_pProcVersion);
+       RemoveProcEntrySeq(g_pProcSysNodes);
+
+       while (dir->subdir)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
+
+               RemoveProcEntry(dir->subdir->name);
+       }
+
+       remove_proc_entry(PVRProcDirRoot, NULL);
+}
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
+{
+       SYS_DATA *psSysData;
+       IMG_CHAR *pszSystemVersionString = "None";
+
+       if(el == PVR_PROC_SEQ_START_TOKEN)
+       {
+               seq_printf(sfile,
+                               "Version %s (%s) %s\n",
+                               PVRVERSION_STRING,
+                               PVR_BUILD_TYPE, PVR_BUILD_DIR);
+               return;
+       }
+
+       psSysData = SysAcquireDataNoCheck();
+       if(psSysData != IMG_NULL && psSysData->pszVersionString != IMG_NULL)
+       {
+               pszSystemVersionString = psSysData->pszVersionString;
+       }
+
+       seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
+}
+
+static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+    switch (deviceType)
+    {
+        default:
+        {
+            static IMG_CHAR text[10];
+
+            sprintf(text, "?%x", (IMG_UINT)deviceType);
+
+            return text;
+        }
+    }
+}
+
+
+static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
+{
+    switch (deviceClass)
+    {
+       case PVRSRV_DEVICE_CLASS_3D:
+       {
+           return "3D";
+       }
+       case PVRSRV_DEVICE_CLASS_DISPLAY:
+       {
+           return "display";
+       }
+       case PVRSRV_DEVICE_CLASS_BUFFER:
+       {
+           return "buffer";
+       }
+       default:
+       {
+           static IMG_CHAR text[10];
+
+           sprintf(text, "?%x", (IMG_UINT)deviceClass);
+           return text;
+       }
+    }
+}
+
+static IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
+{
+       off_t *pOff = va_arg(va, off_t*);
+       if (--(*pOff))
+       {
+               return IMG_NULL;
+       }
+       else
+       {
+               return psNode;
+       }
+}
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
+{
+       PVRSRV_DEVICE_NODE *psDevNode;
+
+       if(el == PVR_PROC_SEQ_START_TOKEN)
+       {
+               seq_printf( sfile,
+                                               "Registered nodes\n"
+                                               "Addr     Type     Class    Index Ref pvDev     Size Res\n");
+               return;
+       }
+
+       psDevNode = (PVRSRV_DEVICE_NODE*)el;
+
+       seq_printf( sfile,
+                         "%p %-8s %-8s %4d  %2u  %p  %3u  %p\n",
+                         psDevNode,
+                         deviceTypeToString(psDevNode->sDevId.eDeviceType),
+                         deviceClassToString(psDevNode->sDevId.eDeviceClass),
+                         psDevNode->sDevId.eDeviceClass,
+                         psDevNode->ui32RefCount,
+                         psDevNode->pvDevice,
+                         psDevNode->ui32pvDeviceSize,
+                         psDevNode->hResManContext);
+}
+
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
+{
+    SYS_DATA *psSysData;
+    PVRSRV_DEVICE_NODE*psDevNode = IMG_NULL;
+    
+    PVR_UNREFERENCED_PARAMETER(sfile);
+    
+    if(!off)
+    {
+       return PVR_PROC_SEQ_START_TOKEN;
+    }
+
+    psSysData = SysAcquireDataNoCheck();
+    if (psSysData != IMG_NULL)
+    {
+       
+       psDevNode = (PVRSRV_DEVICE_NODE*)
+                       List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+                                                                                                       DecOffPsDev_AnyVaCb,
+                                                                                                       &off);
+    }
+
+    
+    return (void*)psDevNode;
+}
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/proc.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/proc.h
new file mode 100644 (file)
index 0000000..823b666
--- /dev/null
@@ -0,0 +1,108 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __SERVICES_PROC_H__
+#define __SERVICES_PROC_H__
+
+#include <asm/system.h>                
+#include <linux/proc_fs.h>     
+#include <linux/seq_file.h> 
+
+#define END_OF_FILE (off_t) -1
+
+typedef off_t (pvr_read_proc_t)(IMG_CHAR *, size_t, off_t);
+
+
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
+typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
+typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
+typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
+
+typedef struct _PVR_PROC_SEQ_HANDLERS_ {
+       pvr_next_proc_seq_t *next;      
+       pvr_show_proc_seq_t *show;      
+       pvr_off2element_proc_seq_t *off2element;
+       pvr_startstop_proc_seq_t *startstop;
+       IMG_VOID *data;
+} PVR_PROC_SEQ_HANDLERS;
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+       __attribute__((format(printf, 4, 5)));
+
+IMG_INT CreateProcEntries(IMG_VOID);
+
+IMG_INT CreateProcReadEntry (const IMG_CHAR * name, pvr_read_proc_t handler);
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemoveProcEntries(IMG_VOID);
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+                                                               const IMG_CHAR* name, 
+                                                               IMG_VOID* data,
+                                                               pvr_next_proc_seq_t next_handler, 
+                                                               pvr_show_proc_seq_t show_handler,
+                                                               pvr_off2element_proc_seq_t off2element_handler,
+                                                               pvr_startstop_proc_seq_t startstop_handler
+                                                          );
+
+struct proc_dir_entry* CreateProcEntrySeq (
+                                                               const IMG_CHAR* name, 
+                                                               IMG_VOID* data,
+                                                               pvr_next_proc_seq_t next_handler, 
+                                                               pvr_show_proc_seq_t show_handler,
+                                                               pvr_off2element_proc_seq_t off2element_handler,
+                                                               pvr_startstop_proc_seq_t startstop_handler,
+                                                               write_proc_t whandler
+                                                          );
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+                                                               const IMG_CHAR* name, 
+                                                               IMG_VOID* data,
+                                                               pvr_next_proc_seq_t next_handler, 
+                                                               pvr_show_proc_seq_t show_handler,
+                                                               pvr_off2element_proc_seq_t off2element_handler,
+                                                               pvr_startstop_proc_seq_t startstop_handler,
+                                                               write_proc_t whandler
+                                                          );
+
+
+IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry);
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry);
+
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_bridge_k.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
new file mode 100644 (file)
index 0000000..f7a41f6
--- /dev/null
@@ -0,0 +1,592 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+#include "mutex.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "sgx_options.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+
+#ifdef MODULE_TEST
+#include "pvr_test_bridge.h"
+#include "kern_test.h"
+#endif
+
+
+#if defined(SUPPORT_DRI_DRM)
+#define        PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define        PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+
+static struct proc_dir_entry *g_ProcBridgeStats =0;
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
+
+#endif
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+static IMG_UINT64 ui64Stamp;
+#endif 
+
+PVRSRV_ERROR
+LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+       {
+               g_ProcBridgeStats = CreateProcReadEntrySeq(
+                                                                                                 "bridge_stats", 
+                                                                                                 NULL,
+                                                                                                 ProcSeqNextBridgeStats,
+                                                                                                 ProcSeqShowBridgeStats,
+                                                                                                 ProcSeqOff2ElementBridgeStats,
+                                                                                                 ProcSeqStartstopBridgeStats
+                                                                                                );
+               if(!g_ProcBridgeStats)
+               {
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+       }
+#endif
+       return CommonBridgeInit();
+}
+
+IMG_VOID
+LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+    RemoveProcEntrySeq(g_ProcBridgeStats);
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start) 
+{
+       if(start) 
+       {
+               LinuxLockMutex(&gPVRSRVLock);
+       }
+       else
+       {
+               LinuxUnLockMutex(&gPVRSRVLock);
+       }
+}
+
+
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
+{
+       if(!off) 
+       {
+               return PVR_PROC_SEQ_START_TOKEN;
+       }
+
+       if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+       {
+               return (void*)0;
+       }
+
+
+       return (void*)&g_BridgeDispatchTable[off-1];
+}
+
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
+{
+       return ProcSeqOff2ElementBridgeStats(sfile,off);
+}
+
+
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
+{
+       PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
+
+       if(el == PVR_PROC_SEQ_START_TOKEN) 
+       {
+               seq_printf(sfile,
+                                                 "Total ioctl call count = %u\n"
+                                                 "Total number of bytes copied via copy_from_user = %u\n"
+                                                 "Total number of bytes copied via copy_to_user = %u\n"
+                                                 "Total number of bytes copied via copy_*_user = %u\n\n"
+                                                 "%-45s | %-40s | %10s | %20s | %10s\n",
+                                                 g_BridgeGlobalStats.ui32IOCTLCount,
+                                                 g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+                                                 g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+                                                 g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+                                                 "Bridge Name",
+                                                 "Wrapper Function",
+                                                 "Call Count",
+                                                 "copy_from_user Bytes",
+                                                 "copy_to_user Bytes"
+                                                );
+               return;
+       }
+
+       seq_printf(sfile,
+                                  "%-45s   %-40s   %-10u   %-20u   %-10u\n",
+                                  psEntry->pszIOCName,
+                                  psEntry->pszFunctionName,
+                                  psEntry->ui32CallCount,
+                                  psEntry->ui32CopyFromUserTotalBytes,
+                                  psEntry->ui32CopyToUserTotalBytes);
+}
+
+#endif 
+
+static inline int support_secure_fd_export(void)
+{
+       unsigned long mask;
+
+       PVRSRV_SGXDEV_INFO *dev_info = pvr_get_sgx_dev_info();
+
+       if (!dev_info)
+               return 0;
+
+       mask = 1 << PVR_DISABLE_SECURE_FD_EXPORT_OFFSET;
+
+       return !(dev_info->ui32ClientBuildOptions & mask);
+}
+
+static int secure_fd_export_prepare(int cmd, void *param_in, void *sec_meminfo)
+{
+       if (!support_secure_fd_export())
+               return 0;
+
+       switch (cmd) {
+       case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+               if (sec_meminfo) {
+                       pr_err("pvr: %s: can only export one MemInfo "
+                                        "per file descriptor", __func__);
+                       return -EINVAL;
+               }
+               break;
+
+       case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+       {
+               PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *map_devmem_in = param_in;
+
+               if (!sec_meminfo) {
+                       pr_err("pvr: %s: file descriptor has no "
+                                        "associated MemInfo handle", __func__);
+                       return -EINVAL;
+               }
+               map_devmem_in->hKernelMemInfo = sec_meminfo;
+               break;
+       }
+
+       default:
+               if (sec_meminfo) {
+                       pr_err("pvr: %s: import/export handle tried "
+                                        "to use privileged service", __func__);
+                       return -EINVAL;
+               }
+               break;
+       }
+
+       return 0;
+}
+
+static void secure_fd_export_finish(int cmd, void *param_out,
+                               void **sec_mem_info, u64 *time_stamp)
+{
+       PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *map_devmem_out = param_out;
+
+       if (!support_secure_fd_export())
+               return;
+
+       if (cmd != PVRSRV_BRIDGE_EXPORT_DEVICEMEM)
+               return;
+
+       *sec_mem_info = map_devmem_out->hMemInfo;
+
+       ui64Stamp++;
+       *time_stamp = ui64Stamp;
+       map_devmem_out->ui64Stamp = ui64Stamp;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT
+PVRSRV_BridgeDispatchKM(struct drm_device unref__ *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+IMG_INT32
+PVRSRV_BridgeDispatchKM(struct file *pFile, IMG_UINT unref__ ioctlCmd, IMG_UINT32 arg)
+#endif
+{
+       IMG_UINT32 cmd;
+#if !defined(SUPPORT_DRI_DRM)
+       PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+       PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+       PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+       IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+       PVRSRV_PER_PROCESS_DATA *psPerProc;
+       PVRSRV_FILE_PRIVATE_DATA *priv_data = PRIVATE_DATA(pFile);
+       IMG_INT err = -EFAULT;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+       psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+       PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+       psBridgePackageKM = &sBridgePackageKM;
+
+       if(!OSAccessOK(PVR_VERIFY_WRITE,
+                                  psBridgePackageUM,
+                                  sizeof(PVRSRV_BRIDGE_PACKAGE)))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+                                __FUNCTION__));
+
+               goto unlock_and_return;
+       }
+       
+       
+       if(OSCopyFromUser(IMG_NULL,
+                                         psBridgePackageKM,
+                                         psBridgePackageUM,
+                                         sizeof(PVRSRV_BRIDGE_PACKAGE))
+         != PVRSRV_OK)
+       {
+               goto unlock_and_return;
+       }
+#endif
+
+       cmd = psBridgePackageKM->ui32BridgeID;
+
+#if defined(MODULE_TEST)
+       switch (cmd)
+       {
+               case PVRSRV_BRIDGE_SERVICES_TEST_MEM1:
+                       {
+                               PVRSRV_ERROR eError = MemTest1();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+               case PVRSRV_BRIDGE_SERVICES_TEST_MEM2:
+                       {
+                               PVRSRV_ERROR eError = MemTest2();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE:
+                       {
+                               PVRSRV_ERROR eError = ResourceTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT:
+                       {
+                               PVRSRV_ERROR eError = EventObjectTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING:
+                       {
+                               PVRSRV_ERROR eError = MemMappingTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID:
+                       {
+                               PVRSRV_ERROR eError = ProcessIDTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS:
+                       {
+                               PVRSRV_ERROR eError = ClockusWaitusTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_TIMER:
+                       {
+                               PVRSRV_ERROR eError = TimerTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV:
+                       {
+                               PVRSRV_ERROR eError = PrivSrvTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+               case PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA:
+               {
+                       IMG_UINT32               ui32PID;
+                       PVRSRV_PER_PROCESS_DATA *psPerProc;
+                       PVRSRV_ERROR eError;
+                       
+                       ui32PID = OSGetCurrentProcessIDKM();
+               
+                       PVRSRVTrace("PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA %d", ui32PID);
+                       
+                       psPerProc = PVRSRVPerProcessData(ui32PID);
+                                               
+                       eError = CopyDataTest(psBridgePackageKM->pvParamIn, psBridgePackageKM->pvParamOut, psPerProc);
+                       
+                       *(PVRSRV_ERROR*)psBridgePackageKM->pvParamOut = eError;
+                       err = 0;
+                       goto unlock_and_return;
+               }
+
+
+               case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT:
+                       {
+                               PVRSRV_ERROR eError = PowerMgmtTest();
+                               if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+                               {
+                                       PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+                                       pReturn->eError = eError;
+                               }
+                       }
+                       err = 0;
+                       goto unlock_and_return;
+
+       }
+#endif
+       
+       if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
+       {
+               PVRSRV_ERROR eError;
+
+               eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+                                                                       (IMG_PVOID *)&psPerProc,
+                                                                       psBridgePackageKM->hKernelServices,
+                                                                       PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+               if(eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+                                        __FUNCTION__, eError));
+                       goto unlock_and_return;
+               }
+
+               if(psPerProc->ui32PID != ui32PID)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+                                        "belonging to process %d", __FUNCTION__, ui32PID,
+                                        psPerProc->ui32PID));
+                       goto unlock_and_return;
+               }
+       }
+       else
+       {
+               
+               psPerProc = PVRSRVPerProcessData(ui32PID);
+               if(psPerProc == IMG_NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+                                        "Couldn't create per-process data area"));
+                       goto unlock_and_return;
+               }
+       }
+
+       psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+       /*
+        * FIXME: remove the following workaround, once all user space libraries
+        * have a proper fix for this security issue.
+        */
+       err = secure_fd_export_prepare(cmd, psBridgePackageKM->pvParamIn,
+                                    priv_data->sec_fd_exp_meminfo);
+       if (err < 0)
+               goto unlock_and_return;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+       switch(cmd)
+       {
+               case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+               case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+               {
+                       PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+                       IMG_INT authenticated = pFile->authenticated;
+                       PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+                       if (authenticated)
+                       {
+                               break;
+                       }
+
+                       
+                       psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
+                       if (psEnvPerProc == IMG_NULL)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
+                               err = -EFAULT;
+                               goto unlock_and_return;
+                       }
+
+                       list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
+                       {
+                               struct drm_file *psDRMFile = psPrivateData->psDRMFile;
+
+                               if (pFile->master == psDRMFile->master)
+                               {
+                                       authenticated |= psDRMFile->authenticated;
+                                       if (authenticated)
+                                       {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (!authenticated)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
+                               err = -EPERM;
+                               goto unlock_and_return;
+                       }
+                       break;
+               }
+               default:
+                       break;
+       }
+#endif 
+
+       err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+       if(err != PVRSRV_OK)
+               goto unlock_and_return;
+
+       /*
+        * FIXME: remove the following workaround, once all user space libraries
+        * have a proper fix for this security issue.
+        */
+       secure_fd_export_finish(cmd, psBridgePackageKM->pvParamOut,
+                               &priv_data->sec_fd_exp_meminfo,
+                               &priv_data->ui64Stamp);
+       switch(cmd)
+       {
+#if defined(SUPPORT_MEMINFO_IDS)
+               case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+               {
+                       PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+                               (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
+                       PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+                       psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp =     psPrivateData->ui64Stamp;
+                       break;
+               }
+
+               case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+               {
+                       PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+                               (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut;
+                       psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp;
+                       break;
+               }
+#endif 
+
+               default:
+                       break;
+       }
+
+unlock_and_return:
+       LinuxUnLockMutex(&gPVRSRVLock);
+       return err;
+}
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_debug.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_debug.c
new file mode 100644 (file)
index 0000000..4f4eae5
--- /dev/null
@@ -0,0 +1,415 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>                      
+#include <stdarg.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "proc.h"
+#include "mutex.h"
+#include "linkage.h"
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+                                                const IMG_CHAR* pszFormat, va_list VArgs)
+                                                IMG_FORMAT_PRINTF(3, 0);
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#define PVR_MAX_FILEPATH_LEN 256
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+                                               const IMG_CHAR *pszFormat, ...)
+                                               IMG_FORMAT_PRINTF(3, 4);
+
+IMG_UINT32 gPVRDebugLevel =
+       (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
+
+#endif 
+
+#define        PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+static PVRSRV_LINUX_MUTEX gsDebugMutexNonIRQ;
+
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
+
+#if !defined (USE_SPIN_LOCK)  
+#define        USE_SPIN_LOCK (in_interrupt() || !preemptible())
+#endif
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+       if (USE_SPIN_LOCK)
+       {
+               spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+       }
+       else
+       {
+               LinuxLockMutex(&gsDebugMutexNonIRQ);
+       }
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+       if (USE_SPIN_LOCK)
+       {
+               spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+       }
+       else
+       {
+               LinuxUnLockMutex(&gsDebugMutexNonIRQ);
+       }
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+       if (USE_SPIN_LOCK)
+       {
+               *ppszBuf = gszBufferIRQ;
+               *pui32BufSiz = sizeof(gszBufferIRQ);
+       }
+       else
+       {
+               *ppszBuf = gszBufferNonIRQ;
+               *pui32BufSiz = sizeof(gszBufferNonIRQ);
+       }
+}
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
+{
+       IMG_UINT32 ui32Used;
+       IMG_UINT32 ui32Space;
+       IMG_INT32 i32Len;
+
+       ui32Used = strlen(pszBuf);
+       BUG_ON(ui32Used >= ui32BufSiz);
+       ui32Space = ui32BufSiz - ui32Used;
+
+       i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+       pszBuf[ui32BufSiz - 1] = 0;
+
+       
+       return (i32Len < 0 || i32Len >= (IMG_INT32)ui32Space) ? IMG_TRUE : IMG_FALSE;
+}
+
+IMG_VOID PVRDPFInit(IMG_VOID)
+{
+    LinuxInitMutex(&gsDebugMutexNonIRQ);
+}
+
+IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+       va_list vaArgs;
+       unsigned long ulLockFlags = 0;
+       IMG_CHAR *pszBuf;
+       IMG_UINT32 ui32BufSiz;
+
+       SelectBuffer(&pszBuf, &ui32BufSiz);
+
+       va_start(vaArgs, pszFormat);
+
+       GetBufferLock(&ulLockFlags);
+       strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+
+       if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+       {
+               printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+       }
+       else
+       {
+               printk(KERN_INFO "%s\n", pszBuf);
+       }
+
+       ReleaseBufferLock(ulLockFlags);
+       va_end(vaArgs);
+
+}
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
+{
+       PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
+       BUG();
+}
+
+#endif 
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
+{
+       va_list VArgs;
+       unsigned long ulLockFlags = 0;
+       IMG_CHAR *pszBuf;
+       IMG_UINT32 ui32BufSiz;
+
+       SelectBuffer(&pszBuf, &ui32BufSiz);
+
+       va_start(VArgs, pszFormat);
+
+       GetBufferLock(&ulLockFlags);
+
+       strncpy(pszBuf, "PVR: ", (ui32BufSiz -1));
+
+       if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+       {
+               printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+       }
+       else
+       {
+               printk(KERN_INFO "%s\n", pszBuf);
+       }
+
+       ReleaseBufferLock(ulLockFlags);
+
+       va_end(VArgs);
+}
+
+#endif 
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
+{
+       va_list VArgs;
+       IMG_BOOL bTrunc;
+
+       va_start (VArgs, pszFormat);
+
+       bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+       va_end (VArgs);
+
+       return bTrunc;
+}
+
+IMG_VOID PVRSRVDebugPrintf     (
+                                               IMG_UINT32      ui32DebugLevel,
+                                               const IMG_CHAR* pszFullFileName,
+                                               IMG_UINT32      ui32Line,
+                                               const IMG_CHAR* pszFormat,
+                                               ...
+                                       )
+{
+       IMG_BOOL bTrace;
+       const IMG_CHAR *pszFileName = pszFullFileName;
+       IMG_CHAR *pszLeafName;
+
+
+       bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
+
+       if (gPVRDebugLevel & ui32DebugLevel)
+       {
+               va_list vaArgs;
+               unsigned long ulLockFlags = 0;
+               IMG_CHAR *pszBuf;
+               IMG_UINT32 ui32BufSiz;
+
+               SelectBuffer(&pszBuf, &ui32BufSiz);
+
+               va_start(vaArgs, pszFormat);
+
+               GetBufferLock(&ulLockFlags);
+
+               
+               if (bTrace == IMG_FALSE)
+               {
+                       switch(ui32DebugLevel)
+                       {
+                               case DBGPRIV_FATAL:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               case DBGPRIV_ERROR:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               case DBGPRIV_WARNING:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               case DBGPRIV_MESSAGE:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               case DBGPRIV_VERBOSE:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
+                                       break;
+                               }
+                               default:
+                               {
+                                       strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1));
+                                       break;
+                               }
+                       }
+               }
+               else
+               {
+                       strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+               }
+
+               if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+               {
+                       printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+               }
+               else
+               {
+                       
+                       if (bTrace == IMG_FALSE)
+                       {
+#ifdef DEBUG_LOG_PATH_TRUNCATE
+                               
+                               static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
+
+                               IMG_CHAR* pszTruncIter;
+                               IMG_CHAR* pszTruncBackInter;
+
+                               
+                               pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
+
+                               
+                               strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
+
+                               if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
+                                       IMG_CHAR szTruncateMassage[] = "FILENAME TRUNCATED";
+                                       strcpy(szFileNameRewrite + (PVR_MAX_FILEPATH_LEN - 1 - strlen(szTruncateMassage)), szTruncateMassage);
+                               }
+
+                               pszTruncIter = szFileNameRewrite;
+                               while(*pszTruncIter++ != 0)
+                               {
+                                       IMG_CHAR* pszNextStartPoint;
+                                       
+                                       if(
+                                          !( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
+                                                ( *(pszTruncIter-1) == '.') &&
+                                                ( *(pszTruncIter-2) == '.') &&
+                                                ( *(pszTruncIter-3) == '/') )
+                                          ) continue;
+
+                                       
+                                       pszTruncBackInter = pszTruncIter - 3;
+                                       while(*(--pszTruncBackInter) != '/')
+                                       {
+                                               if(pszTruncBackInter <= szFileNameRewrite) break;
+                                       }
+                                       pszNextStartPoint = pszTruncBackInter;
+
+                                       
+                                       while(*pszTruncIter != 0)
+                                       {
+                                               *pszTruncBackInter++ = *pszTruncIter++;
+                                       }
+                                       *pszTruncBackInter = 0;
+
+                                       
+                                       pszTruncIter = pszNextStartPoint;
+                               }
+
+                               pszFileName = szFileNameRewrite;
+                               
+                               if(*pszFileName == '/') pszFileName++;
+#endif
+
+#if !defined(__sh__)
+                               pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '\\');
+
+                               if (pszLeafName)
+                               {
+                                       pszFileName = pszLeafName;
+                       }
+#endif 
+
+                               if (BAppend(pszBuf, ui32BufSiz, " [%u, %s]", ui32Line, pszFileName))
+                               {
+                                       printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+                               }
+                               else
+                               {
+                                       printk(KERN_INFO "%s\n", pszBuf);
+                               }
+                       }
+                       else
+                       {
+                               printk(KERN_INFO "%s\n", pszBuf);
+                       }
+               }
+
+               ReleaseBufferLock(ulLockFlags);
+
+               va_end (vaArgs);
+       }
+}
+
+#endif 
+
+#if defined(DEBUG)
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+#define        _PROC_SET_BUFFER_SZ             2
+       IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+
+       if (count != _PROC_SET_BUFFER_SZ)
+       {
+               return -EINVAL;
+       }
+       else
+       {
+               if (copy_from_user(data_buffer, buffer, count))
+                       return -EINVAL;
+               if (data_buffer[count - 1] != '\n')
+                       return -EINVAL;
+               gPVRDebugLevel = data_buffer[0] - '0';
+       }
+       return (count);
+}
+
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)
+{
+       seq_printf(sfile, "%u\n", gPVRDebugLevel);
+}
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_drm.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_drm.c
new file mode 100644 (file)
index 0000000..e3fb471
--- /dev/null
@@ -0,0 +1,358 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <asm/ioctl.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "pvr_bridge.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "pvrversion.h"
+#include "lock.h"
+#include "linkage.h"
+#include "pvr_drm.h"
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+#include "pvr_drm_mod.h"
+#endif
+
+#define PVR_DRM_NAME   PVRSRV_MODNAME
+#define PVR_DRM_DESC   "Imagination Technologies PVR DRM"
+
+#if !defined(PVR_DRI_DRM_NOT_PCI)
+struct pci_dev *gpsPVRLDMDev;
+#endif
+
+struct drm_device *gpsPVRDRMDev;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+#error "Linux kernel version 2.6.25 or later required for PVR DRM support"
+#endif
+
+#define PVR_DRM_FILE struct drm_file *
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static struct pci_device_id asPciIdList[] = {
+#if defined(PVR_DRI_DRM_NOT_PCI)
+       {1, 1, 1, 1, 0, 0, 0},
+#else
+       {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#if defined(SYS_SGX_DEV1_DEVICE_ID)
+       {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#endif
+       {0}
+};
+#endif
+
+DRI_DRM_STATIC IMG_INT
+PVRSRVDrmLoad(struct drm_device *dev, IMG_UINT32 flags)
+{
+       IMG_INT iRes;
+
+       PVR_TRACE(("PVRSRVDrmLoad"));
+
+       gpsPVRDRMDev = dev;
+#if !defined(PVR_DRI_DRM_NOT_PCI)
+       gpsPVRLDMDev = dev->pdev;
+#endif
+
+#if defined(PDUMP)
+       iRes = dbgdrv_init();
+       if (iRes != 0)
+       {
+               return iRes;
+       }
+#endif
+       
+       iRes = PVRCore_Init();
+       if (iRes != 0)
+       {
+               goto exit_dbgdrv_cleanup;
+       }
+
+#if defined(DISPLAY_CONTROLLER)
+       iRes = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(dev);
+       if (iRes != 0)
+       {
+               goto exit_pvrcore_cleanup;
+       }
+#endif
+       return 0;
+
+#if defined(DISPLAY_CONTROLLER)
+exit_pvrcore_cleanup:
+       PVRCore_Cleanup();
+#endif
+exit_dbgdrv_cleanup:
+#if defined(PDUMP)
+       dbgdrv_cleanup();
+#endif
+       return iRes;
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRSRVDrmUnload(struct drm_device *dev)
+{
+       PVR_TRACE(("PVRSRVDrmUnload"));
+
+#if defined(DISPLAY_CONTROLLER)
+       PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev);
+#endif
+
+       PVRCore_Cleanup();
+
+#if defined(PDUMP)
+       dbgdrv_cleanup();
+#endif
+
+       return 0;
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file)
+{
+       return PVRSRVOpen(dev, file);
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT) && !defined(PVR_LINUX_USING_WORKQUEUES)
+DRI_DRM_STATIC void
+PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+{
+       PVRSRVRelease(file->driver_priv);
+
+       file->driver_priv = NULL;
+}
+#else
+DRI_DRM_STATIC IMG_INT
+PVRSRVDrmRelease(struct inode *inode, struct file *filp)
+{
+       struct drm_file *file_priv = filp->private_data;
+       void *psDriverPriv = file_priv->driver_priv;
+       IMG_INT ret;
+
+       ret = drm_release(inode, filp);
+
+       if (ret != 0)
+       {
+
+               PVR_DPF((PVR_DBG_ERROR, "%s : drm_release failed: %d",
+                       __FUNCTION__, ret));
+}
+
+       PVRSRVRelease(psDriverPriv);
+
+       return 0;
+}
+#endif
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMIsMaster(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+       return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+IMG_INT
+PVRDRM_Dummy_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+       return 0;
+}
+#endif
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMUnprivCmd(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+       IMG_INT ret = 0;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       if (arg == NULL)
+       {
+               ret = -EFAULT;
+       }
+       else
+       {
+               IMG_UINT32 *pui32Args = (IMG_UINT32 *)arg;
+               IMG_UINT32 ui32Cmd = pui32Args[0];
+               IMG_UINT32 *pui32OutArg = (IMG_UINT32 *)arg;
+
+               switch (ui32Cmd)
+               {
+                       case PVR_DRM_UNPRIV_INIT_SUCCESFUL:
+                               *pui32OutArg = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
+                               break;
+
+                       default:
+                               ret = -EFAULT;
+               }
+
+       }
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+
+       return ret;
+}
+
+#if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+static IMG_INT
+PVRDRM_Display_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+       IMG_INT res;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       res = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(dev, arg, pFile);
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+
+       return res;
+}
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+#define        PVR_DRM_FOPS_IOCTL      .unlocked_ioctl
+#define        PVR_DRM_UNLOCKED        DRM_UNLOCKED
+#else
+#define        PVR_DRM_FOPS_IOCTL      .ioctl
+#define        PVR_DRM_UNLOCKED        0
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+struct drm_ioctl_desc sPVRDrmIoctls[] = {
+       DRM_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, PVR_DRM_UNLOCKED),
+       DRM_IOCTL_DEF(PVR_DRM_IS_MASTER_IOCTL, PVRDRMIsMaster, DRM_MASTER | PVR_DRM_UNLOCKED),
+       DRM_IOCTL_DEF(PVR_DRM_UNPRIV_IOCTL, PVRDRMUnprivCmd, PVR_DRM_UNLOCKED),
+#if defined(PDUMP)
+       DRM_IOCTL_DEF(PVR_DRM_DBGDRV_IOCTL, dbgdrv_ioctl, PVR_DRM_UNLOCKED),
+#endif
+#if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+       DRM_IOCTL_DEF(PVR_DRM_DISP_IOCTL, PVRDRM_Display_ioctl, DRM_MASTER | PVR_DRM_UNLOCKED)
+#endif
+};
+
+static IMG_INT pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+
+static struct drm_driver sPVRDrmDriver = 
+{
+       .driver_features = 0,
+       .dev_priv_size = 0,
+       .load = PVRSRVDrmLoad,
+       .unload = PVRSRVDrmUnload,
+       .open = PVRSRVDrmOpen,
+       .suspend = PVRSRVDriverSuspend,
+       .resume = PVRSRVDriverResume,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = sPVRDrmIoctls,
+       .fops = 
+       {
+               .owner = THIS_MODULE,
+               .open = drm_open,
+               .release = PVRSRVDrmRelease,
+               PVR_DRM_FOPS_IOCTL = drm_ioctl,
+               .mmap = PVRMMap,
+               .poll = drm_poll,
+               .fasync = drm_fasync,
+       },
+       .pci_driver = 
+       {
+               .name = PVR_DRM_NAME,
+               .id_table = asPciIdList,
+       },
+               
+       .name = PVR_DRM_NAME,
+       .desc = PVR_DRM_DESC,
+       .date = PVR_BUILD_DATE,
+       .major = PVRVERSION_MAJ,
+       .minor = PVRVERSION_MIN,
+       .patchlevel = PVRVERSION_BUILD,
+};
+
+static IMG_INT __init PVRSRVDrmInit(void)
+{
+       IMG_INT iRes;
+       sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+
+       
+       PVRDPFInit();
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+       iRes = drm_pvr_dev_add();
+       if (iRes != 0)
+       {
+               return iRes;
+       }
+#endif
+
+       iRes = drm_init(&sPVRDrmDriver);
+#if defined(PVR_DRI_DRM_NOT_PCI)
+       if (iRes != 0)
+       {
+               drm_pvr_dev_remove();
+       }
+#endif
+       return iRes;
+}
+       
+static void __exit PVRSRVDrmExit(void)
+{
+       drm_exit(&sPVRDrmDriver);
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+       drm_pvr_dev_remove();
+#endif
+}
+
+module_init(PVRSRVDrmInit);
+module_exit(PVRSRVDrmExit);
+#endif 
+#endif 
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_drm.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/pvr_drm.h
new file mode 100644 (file)
index 0000000..21b1b35
--- /dev/null
@@ -0,0 +1,90 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
+
+#include "pvr_drm_shared.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#define        PVR_DRM_MAKENAME_HELPER(x, y) x ## y
+#define        PVR_DRM_MAKENAME(x, y) PVR_DRM_MAKENAME_HELPER(x, y)
+
+IMG_INT PVRCore_Init(IMG_VOID);
+IMG_VOID PVRCore_Cleanup(IMG_VOID);
+IMG_INT PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
+IMG_VOID PVRSRVRelease(IMG_VOID *pvPrivData);
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice);
+
+IMG_INT PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define        DRI_DRM_STATIC
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, IMG_UINT32 flags);
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev);
+IMG_INT PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+DRI_DRM_STATIC IMG_INT PVRSRVDrmRelease(struct inode *inode, struct file *filp);
+#else
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file);
+#endif
+IMG_INT PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#else
+#define        DRI_DRM_STATIC  static
+#endif 
+
+#if defined(DISPLAY_CONTROLLER)
+extern IMG_INT PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
+extern IMG_VOID PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device *);
+extern IMG_INT PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Suspend)(struct drm_device *);
+extern IMG_INT PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Resume)(struct drm_device *);
+#if defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+extern IMG_INT PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+#endif
+
+#if defined(PDUMP)
+IMG_INT dbgdrv_init(IMG_VOID);
+IMG_VOID dbgdrv_cleanup(IMG_VOID);
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+#define        PVR_DRM_SRVKM_IOCTL     _IO(0, PVR_DRM_SRVKM_CMD)
+#define        PVR_DRM_IS_MASTER_IOCTL _IO(0, PVR_DRM_IS_MASTER_CMD)
+#define        PVR_DRM_UNPRIV_IOCTL    _IO(0, PVR_DRM_UNPRIV_CMD)
+#define        PVR_DRM_DBGDRV_IOCTL    _IO(0, PVR_DRM_DBGDRV_CMD)
+#define        PVR_DRM_DISP_IOCTL      _IO(0, PVR_DRM_DISP_CMD)
+#endif
+
+#endif
+
+#endif 
+
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgx535defs.h b/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgx535defs.h
new file mode 100644 (file)
index 0000000..04f43be
--- /dev/null
@@ -0,0 +1,650 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _SGX535DEFS_KM_H_
+#define _SGX535DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK      0x00000003U
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT     0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x00003000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00030000U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK     0x00300000U
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT    20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATESTATUS                0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK   0x00000001
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT  0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00001000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00010000U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK  0x00100000U
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR                0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK   0x00000003U
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT  0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x00003000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00030000U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK  0x00300000U
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+#define EUR_CR_CORE_ID                      0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_REVISION                0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2          0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK   0x00000002U
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT  1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000040U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   6
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2                0x0118U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000080U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  7
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000040U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  6
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000020U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  5
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS                 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0xFFF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0xFFFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_PDS_INV2                     0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV2_DSC_SHIFT           0
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x3FFFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00010000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 16
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0xFFFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+#define EUR_CR_BIF_DIR_LIST_BASE1           0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2           0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3           0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4           0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5           0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6           0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7           0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE8           0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE9           0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE10          0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE11          0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE12          0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE13          0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE14          0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE15          0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 12
+#define EUR_CR_BIF_BANK_SET                 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_MASK     0x000003FFU
+#define EUR_CR_BIF_BANK_SET_SELECT_SHIFT    0
+#define EUR_CR_BIF_BANK0                    0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK    0x00000F00U
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK      0x000F0000U
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT     16
+#define EUR_CR_BIF_BANK1                    0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK    0x00000F00U
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK      0x000F0000U
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT     16
+#define EUR_CR_BIF_ADT_TTE                  0x0C80
+#define EUR_CR_BIF_ADT_TTE_VALUE_MASK       0x000000FFU
+#define EUR_CR_BIF_ADT_TTE_VALUE_SHIFT      0
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TWOD_REQ_BASE            0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK  0xFFF00000U
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1      0x0C94
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_MASK 0x00000007U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_MASK 0x00000038U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_MASK 0x000001C0U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_MASK 0x00000E00U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_MASK 0x00007000U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_SHIFT 12
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_MASK 0x00038000U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_SHIFT 15
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2      0x0C98
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_MASK 0x00000007U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_MASK 0x00000038U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_MASK 0x000001C0U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_MASK 0x00000E00U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_CONFIG           0x0CA0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_MASK 0x0000000FU
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_MASK 0x00000FF0U
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT 4
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_MASK 0x00FFF000U
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT 12
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0xFFF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_BIF_BANK_STATUS              0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_2D_SOCIF                     0x0E18
+#define EUR_CR_2D_SOCIF_FREESPACE_MASK      0x000000FFU
+#define EUR_CR_2D_SOCIF_FREESPACE_SHIFT     0
+#define EUR_CR_2D_ALPHA                     0x0E1C
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_MASK  0x0000FF00U
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_SHIFT 8
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_MASK 0x000000FFU
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_SHIFT 0
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       25
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgx540defs.h b/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgx540defs.h
new file mode 100644 (file)
index 0000000..dadbb1e
--- /dev/null
@@ -0,0 +1,547 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _SGX540DEFS_KM_H_
+#define _SGX540DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK     0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT    14
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     18
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK  0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK  0x00003000U
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK  0x00300000U
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK  0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000U
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000U
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  20
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK  0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  18
+#define EUR_CR_POWER                        0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK      0x00000001U
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT     0
+#define EUR_CR_CORE_ID                      0x0020
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_REVISION                0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK    0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK   0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT  6
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   7
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK    0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT   8
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK    0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT   9
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_MADD_RESET_MASK   0x00001000U
+#define EUR_CR_SOFT_RESET_MADD_RESET_SHIFT  12
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK    0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT   13
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK    0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT   14
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   15
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    17
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS                 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+#define EUR_CR_EVENT_KICK1                  0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+#define EUR_CR_EVENT_KICK2                  0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_EVENT_KICK3                  0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x00FFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x00FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x03000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       24
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxdefs.h b/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxdefs.h
new file mode 100644 (file)
index 0000000..9e5effb
--- /dev/null
@@ -0,0 +1,94 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _SGXDEFS_H_
+#define        _SGXDEFS_H_
+
+#include "sgxerrata.h"
+#include "sgxfeaturedefs.h"
+
+#if defined(SGX520)
+#include "sgx520defs.h"
+#else
+#if defined(SGX530)
+#include "sgx530defs.h"
+#else
+#if defined(SGX535)
+#include "sgx535defs.h"
+#else
+#if defined(SGX535_V1_1)
+#include "sgx535defs.h"
+#else
+#if defined(SGX540)
+#include "sgx540defs.h"
+#else
+#if defined(SGX541)
+#include "sgx541defs.h"
+#else
+#if defined(SGX543)
+#include "sgx543defs.h"
+#else
+#if defined(SGX544)
+#include "sgx544defs.h"
+#else
+#if defined(SGX545)
+#include "sgx545defs.h"
+#else
+#if defined(SGX531)
+#include "sgx531defs.h"
+#else
+#if defined(SGX554)
+#include "sgx554defs.h"
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX541)
+#if SGX_CORE_REV == 100
+#include "sgx541_100mpdefs.h"
+#else
+#include "sgx541mpdefs.h"
+#endif 
+#else
+#include "sgxmpdefs.h"
+#endif 
+#else 
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+#include "mnemedefs.h"
+#endif
+#endif 
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxerrata.h b/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxerrata.h
new file mode 100644 (file)
index 0000000..e898939
--- /dev/null
@@ -0,0 +1,362 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _SGXERRATA_KM_H_
+#define _SGXERRATA_KM_H_
+
+#if defined(SGX520) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 100
+               #define FIX_HW_BRN_28889
+       #else
+       #if SGX_CORE_REV == 111
+               #define FIX_HW_BRN_28889
+       #else
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX520 Core Revision unspecified"
+       #endif
+       #endif
+       #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX530) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 110
+               #define FIX_HW_BRN_22934
+               #define FIX_HW_BRN_28889
+       #else
+       #if SGX_CORE_REV == 111
+               #define FIX_HW_BRN_22934        
+               #define FIX_HW_BRN_28889
+       #else
+       #if SGX_CORE_REV == 120
+               #define FIX_HW_BRN_22934        
+               #define FIX_HW_BRN_28889
+       #else
+       #if SGX_CORE_REV == 121
+               #define FIX_HW_BRN_22934        
+               #define FIX_HW_BRN_28889
+       #else
+       #if SGX_CORE_REV == 125
+               #define FIX_HW_BRN_22934        
+               #define FIX_HW_BRN_28889
+       #else
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX530 Core Revision unspecified"
+       #endif
+       #endif
+       #endif
+       #endif
+#endif
+        #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX531) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 101
+               #define FIX_HW_BRN_26620
+               #define FIX_HW_BRN_28011
+       #else
+       #if SGX_CORE_REV == 110
+               
+       #else
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX531 Core Revision unspecified"
+       #endif
+       #endif
+       #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if (defined(SGX535) || defined(SGX535_V1_1)) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 112
+               #define FIX_HW_BRN_23281
+               #define FIX_HW_BRN_23410
+               #define FIX_HW_BRN_22693
+               #define FIX_HW_BRN_22934        
+               #define FIX_HW_BRN_22997
+               #define FIX_HW_BRN_23030
+       #else
+       #if SGX_CORE_REV == 113
+               #define FIX_HW_BRN_22934        
+               #define FIX_HW_BRN_23281
+               #define FIX_HW_BRN_23944
+               #define FIX_HW_BRN_23410
+       #else
+       #if SGX_CORE_REV == 121
+               #define FIX_HW_BRN_22934        
+               #define FIX_HW_BRN_23944
+               #define FIX_HW_BRN_23410
+       #else
+       #if SGX_CORE_REV == 126
+               #define FIX_HW_BRN_22934        
+       #else   
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX535 Core Revision unspecified"
+
+       #endif
+       #endif
+       #endif
+       #endif
+       #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX540) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 101
+               #define FIX_HW_BRN_25499
+               #define FIX_HW_BRN_25503
+               #define FIX_HW_BRN_26620
+               #define FIX_HW_BRN_28011
+       #else
+       #if SGX_CORE_REV == 110
+               #define FIX_HW_BRN_25503
+               #define FIX_HW_BRN_26620
+               #define FIX_HW_BRN_28011
+       #else
+       #if SGX_CORE_REV == 120
+               #define FIX_HW_BRN_26620
+               #define FIX_HW_BRN_28011
+       #else
+       #if SGX_CORE_REV == 121
+               #define FIX_HW_BRN_28011
+       #else
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX540 Core Revision unspecified"
+       #endif
+       #endif
+       #endif
+       #endif
+       #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX541) && !defined(SGX_CORE_DEFINED)
+       #if defined(SGX_FEATURE_MP)
+               
+               #define SGX_CORE_REV_HEAD       0
+               #if defined(USE_SGX_CORE_REV_HEAD)
+                       
+                       #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+               #endif
+
+               #if SGX_CORE_REV == 100
+                       #define FIX_HW_BRN_27270
+                       #define FIX_HW_BRN_28011
+                       #define FIX_HW_BRN_27510
+                       
+               #else
+               #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+                       
+               #else
+                       #error "sgxerrata.h: SGX541 Core Revision unspecified"
+               #endif
+               #endif
+               
+               #define SGX_CORE_DEFINED
+       #else 
+               #error "sgxerrata.h: SGX541 only supports MP configs (SGX_FEATURE_MP)"
+       #endif 
+#endif
+
+#if defined(SGX543) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 113
+               #define FIX_HW_BRN_29997
+               #define FIX_HW_BRN_30954
+               #define FIX_HW_BRN_31093
+               #define FIX_HW_BRN_31195
+                       
+       #else
+       #if SGX_CORE_REV == 122
+               #define FIX_HW_BRN_29997
+                #define FIX_HW_BRN_30954
+               #define FIX_HW_BRN_31093
+               #define FIX_HW_BRN_31195
+                       
+       #else
+       #if SGX_CORE_REV == 140
+                #define FIX_HW_BRN_30954
+                #define FIX_HW_BRN_31195
+
+       #else
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX543 Core Revision unspecified"
+       #endif
+       #endif
+       #endif
+       #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX544) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 100
+               
+       #else
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX544 Core Revision unspecified"
+       #endif
+       #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX545) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 100
+               #define FIX_HW_BRN_26620
+               #define FIX_HW_BRN_27266
+               #define FIX_HW_BRN_27456
+               #define FIX_HW_BRN_29702
+               #define FIX_HW_BRN_29823
+       #else
+       #if SGX_CORE_REV == 109
+               #define FIX_HW_BRN_29702
+               #define FIX_HW_BRN_29823
+       #else
+       #if SGX_CORE_REV == 1012
+               #define FIX_HW_BRN_29823
+       #else
+       #if SGX_CORE_REV == 1013
+               #define FIX_HW_BRN_29823
+       #else
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX545 Core Revision unspecified"
+       #endif
+       #endif
+       #endif
+       #endif
+       #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX554) && !defined(SGX_CORE_DEFINED)
+       
+       #define SGX_CORE_REV_HEAD       0
+       #if defined(USE_SGX_CORE_REV_HEAD)
+               
+               #define SGX_CORE_REV    SGX_CORE_REV_HEAD
+       #endif
+
+       #if SGX_CORE_REV == 100
+               
+       #else
+       #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+               
+       #else
+               #error "sgxerrata.h: SGX554 Core Revision unspecified"
+       #endif
+       #endif
+       
+       #define SGX_CORE_DEFINED
+#endif
+
+#if !defined(SGX_CORE_DEFINED)
+#if defined (__GNUC__)
+       #warning "sgxerrata.h: SGX Core Version unspecified"
+#else
+       #pragma message("sgxerrata.h: SGX Core Version unspecified")
+#endif
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h b/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
new file mode 100644 (file)
index 0000000..714bea3
--- /dev/null
@@ -0,0 +1,198 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if defined(SGX520)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX520"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_520
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (28)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX530)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX530"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_530
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (28)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX531)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX531"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_531
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (28)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+       #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX535)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX535"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_535
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (32)
+       #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+       #define SGX_FEATURE_BIF_NUM_DIRLISTS                                    (16)
+       #define SGX_FEATURE_2D_HARDWARE
+       #define SGX_FEATURE_AUTOCLOCKGATING
+       #define SUPPORT_SGX_GENERAL_MAPPING_HEAP
+#else
+#if defined(SGX540)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX540"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_540
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (28)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+       #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX541)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX541"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_541
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (32)
+       #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+       #define SGX_FEATURE_BIF_NUM_DIRLISTS                                    (8)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+    #define SGX_FEATURE_SPM_MODE_0
+       #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX543)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX543"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_543
+       #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+       #define SGX_FEATURE_USE_UNLIMITED_PHASES
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (32)
+       #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+       #define SGX_FEATURE_BIF_NUM_DIRLISTS                                    (8)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+       #define SGX_FEATURE_MONOLITHIC_UKERNEL
+    #define SGX_FEATURE_SPM_MODE_0
+       #define SGX_FEATURE_MULTI_EVENT_KICK
+       #define SGX_FEATURE_DATA_BREAKPOINTS
+       #define SGX_FEATURE_2D_HARDWARE
+       #define SGX_FEATURE_PTLA
+       #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+#else
+#if defined(SGX544)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX544"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_544
+       #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+       #define SGX_FEATURE_USE_UNLIMITED_PHASES
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (32)
+       #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+       #define SGX_FEATURE_BIF_NUM_DIRLISTS                                    (8)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+       #define SGX_FEATURE_MONOLITHIC_UKERNEL
+    #define SGX_FEATURE_SPM_MODE_0
+       #define SGX_FEATURE_MULTI_EVENT_KICK
+       #define SGX_FEATURE_DATA_BREAKPOINTS
+       #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+#else
+#if defined(SGX545)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX545"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_545
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (32)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+       #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+       #define SGX_FEATURE_USE_UNLIMITED_PHASES
+       #define SGX_FEATURE_VOLUME_TEXTURES
+       #define SGX_FEATURE_HOST_ALLOC_FROM_DPM
+       #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+       #define SGX_FEATURE_BIF_NUM_DIRLISTS                            (16)
+       #define SGX_FEATURE_NUM_USE_PIPES                                       (4)
+       #define SGX_FEATURE_TEXTURESTRIDE_EXTENSION
+       #define SGX_FEATURE_PDS_DATA_INTERLEAVE_2DWORDS
+       #define SGX_FEATURE_MONOLITHIC_UKERNEL
+       #define SGX_FEATURE_ZLS_EXTERNALZ
+       #define SGX_FEATURE_VDM_CONTEXT_SWITCH_REV_2
+       #define SGX_FEATURE_ISP_CONTEXT_SWITCH_REV_2
+       #define SGX_FEATURE_NUM_PDS_PIPES                                       (2)
+       #define SGX_FEATURE_NATIVE_BACKWARD_BLIT
+       #define SGX_FEATURE_MAX_TA_RENDER_TARGETS                               (512)
+       #define SGX_FEATURE_SPM_MODE_0
+       #define SGX_FEATURE_SECONDARY_REQUIRES_USE_KICK
+       #define SGX_FEATURE_WRITEBACK_DCU
+       
+       
+       #define SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+       #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX554)
+       #define SGX_CORE_FRIENDLY_NAME                                                  "SGX554"
+       #define SGX_CORE_ID                                                                             SGX_CORE_ID_554
+       #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+       #define SGX_FEATURE_USE_UNLIMITED_PHASES
+       #define SGX_FEATURE_ADDRESS_SPACE_SIZE                                  (32)
+       #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+       #define SGX_FEATURE_BIF_NUM_DIRLISTS                                    (8)
+       #define SGX_FEATURE_AUTOCLOCKGATING
+       #define SGX_FEATURE_MONOLITHIC_UKERNEL
+    #define SGX_FEATURE_SPM_MODE_0
+       #define SGX_FEATURE_MULTI_EVENT_KICK
+       #define SGX_FEATURE_DATA_BREAKPOINTS
+       #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(FIX_HW_BRN_22693)
+#undef SGX_FEATURE_AUTOCLOCKGATING
+#endif
+
+#if defined(FIX_HW_BRN_27266)
+#undef SGX_FEATURE_36BIT_MMU
+#endif
+
+#if defined(FIX_HW_BRN_27456)
+#undef SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+#endif
+
+#if defined(FIX_HW_BRN_22934)  \
+       || defined(FIX_HW_BRN_25499)
+#undef SGX_FEATURE_MULTI_EVENT_KICK
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+       #if defined(SGX_FEATURE_36BIT_MMU)
+               #error SGX_FEATURE_SYSTEM_CACHE is incompatible with SGX_FEATURE_36BIT_MMU
+       #endif
+       #if defined(FIX_HW_BRN_26620) && !defined(SGX_FEATURE_MULTI_EVENT_KICK)
+               #define SGX_BYPASS_SYSTEM_CACHE
+       #endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if !defined(SGX_FEATURE_MP_CORE_COUNT)
+#error SGX_FEATURE_MP_CORE_COUNT must be defined when SGX_FEATURE_MP is defined
+#endif
+#else
+#define SGX_FEATURE_MP_CORE_COUNT      (1)
+#endif
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && !defined(SUPPORT_SGX_PRIORITY_SCHEDULING)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING
+#endif
+
+#include "img_types.h"
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxmmu.h b/drivers/staging/mrst/pvr/services4/srvkm/hwdefs/sgxmmu.h
new file mode 100644 (file)
index 0000000..4df8003
--- /dev/null
@@ -0,0 +1,79 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__SGXMMU_KM_H__)
+#define __SGXMMU_KM_H__
+
+#define SGX_MMU_PAGE_SHIFT                             (12)
+#define SGX_MMU_PAGE_SIZE                              (1U<<SGX_MMU_PAGE_SHIFT)
+#define SGX_MMU_PAGE_MASK                              (SGX_MMU_PAGE_SIZE - 1U)
+
+#define SGX_MMU_PD_SHIFT                               (10)
+#define SGX_MMU_PD_SIZE                                        (1U<<SGX_MMU_PD_SHIFT)
+#define SGX_MMU_PD_MASK                                        (0xFFC00000U)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+       #define SGX_MMU_PDE_ADDR_MASK                   (0xFFFFFF00U)
+       #define SGX_MMU_PDE_ADDR_ALIGNSHIFT             (4)
+#else
+       #define SGX_MMU_PDE_ADDR_MASK                   (0xFFFFF000U)
+       #define SGX_MMU_PDE_ADDR_ALIGNSHIFT             (0)
+#endif
+#define SGX_MMU_PDE_VALID                              (0x00000001U)
+#define SGX_MMU_PDE_PAGE_SIZE_4K               (0x00000000U)
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+       #define SGX_MMU_PDE_PAGE_SIZE_16K               (0x00000002U)
+       #define SGX_MMU_PDE_PAGE_SIZE_64K               (0x00000004U)
+       #define SGX_MMU_PDE_PAGE_SIZE_256K              (0x00000006U)
+       #define SGX_MMU_PDE_PAGE_SIZE_1M                (0x00000008U)
+       #define SGX_MMU_PDE_PAGE_SIZE_4M                (0x0000000AU)
+       #define SGX_MMU_PDE_PAGE_SIZE_MASK              (0x0000000EU)
+#else
+       #define SGX_MMU_PDE_WRITEONLY                   (0x00000002U)
+       #define SGX_MMU_PDE_READONLY                    (0x00000004U)
+       #define SGX_MMU_PDE_CACHECONSISTENT             (0x00000008U)
+       #define SGX_MMU_PDE_EDMPROTECT                  (0x00000010U)
+#endif
+
+#define SGX_MMU_PT_SHIFT                               (10)
+#define SGX_MMU_PT_SIZE                                        (1U<<SGX_MMU_PT_SHIFT)
+#define SGX_MMU_PT_MASK                                        (0x003FF000U)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+       #define SGX_MMU_PTE_ADDR_MASK                   (0xFFFFFF00U)
+       #define SGX_MMU_PTE_ADDR_ALIGNSHIFT             (4)
+#else
+       #define SGX_MMU_PTE_ADDR_MASK                   (0xFFFFF000U)
+       #define SGX_MMU_PTE_ADDR_ALIGNSHIFT             (0)
+#endif
+#define SGX_MMU_PTE_VALID                              (0x00000001U)
+#define SGX_MMU_PTE_WRITEONLY                  (0x00000002U)
+#define SGX_MMU_PTE_READONLY                   (0x00000004U)
+#define SGX_MMU_PTE_CACHECONSISTENT            (0x00000008U)
+#define SGX_MMU_PTE_EDMPROTECT                 (0x00000010U)
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/buffer_manager.h b/drivers/staging/mrst/pvr/services4/srvkm/include/buffer_manager.h
new file mode 100644 (file)
index 0000000..0a8e0ad
--- /dev/null
@@ -0,0 +1,212 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _BUFFER_MANAGER_H_
+#define _BUFFER_MANAGER_H_
+
+#include "img_types.h"
+#include "ra.h"
+#include "perproc.h"
+
+#if defined(__cplusplus)
+extern "C"{
+#endif 
+       
+typedef struct _BM_HEAP_ BM_HEAP;
+
+struct _BM_MAPPING_
+{
+       enum
+       {
+               hm_wrapped = 1,         
+               hm_wrapped_scatter,     
+               hm_wrapped_virtaddr, 
+               hm_wrapped_scatter_virtaddr, 
+               hm_env,                         
+               hm_contiguous           
+       } eCpuMemoryOrigin;
+
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       BM_CONTEXT                      *pBMContext;
+       BM_HEAP                         *pBMHeap;       
+       RA_ARENA                        *pArena;        
+
+       IMG_CPU_VIRTADDR        CpuVAddr;
+       IMG_CPU_PHYADDR         CpuPAddr;
+       IMG_DEV_VIRTADDR        DevVAddr;
+       IMG_SYS_PHYADDR         *psSysAddr;
+       IMG_SIZE_T                      uSize;
+    IMG_HANDLE          hOSMemHandle;
+       IMG_UINT32                      ui32Flags;
+};
+
+typedef struct _BM_BUF_
+{
+       IMG_CPU_VIRTADDR        *CpuVAddr;
+    IMG_VOID            *hOSMemHandle;
+       IMG_CPU_PHYADDR         CpuPAddr;
+       IMG_DEV_VIRTADDR        DevVAddr;
+
+       BM_MAPPING                      *pMapping;
+       IMG_UINT32                      ui32RefCount;
+       IMG_UINT32                      ui32ExportCount;
+} BM_BUF;
+
+struct _BM_HEAP_
+{
+       IMG_UINT32                              ui32Attribs;
+       BM_CONTEXT                              *pBMContext;
+       RA_ARENA                                *pImportArena;
+       RA_ARENA                                *pLocalDevMemArena;
+       RA_ARENA                                *pVMArena;
+       DEV_ARENA_DESCRIPTOR    sDevArena;
+       MMU_HEAP                                *pMMUHeap;
+       PDUMP_MMU_ATTRIB                *psMMUAttrib;
+       
+       struct _BM_HEAP_                *psNext;
+       struct _BM_HEAP_                **ppsThis;
+};
+
+struct _BM_CONTEXT_
+{
+       MMU_CONTEXT     *psMMUContext;
+
+       
+        BM_HEAP *psBMHeap;
+        
+       
+        BM_HEAP *psBMSharedHeap;
+
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       
+       HASH_TABLE *pBufferHash;
+
+       
+       IMG_HANDLE hResItem;
+
+       IMG_UINT32 ui32RefCount;
+
+       
+
+       struct _BM_CONTEXT_ *psNext;
+       struct _BM_CONTEXT_ **ppsThis;
+};
+
+
+
+typedef IMG_VOID *BM_HANDLE;
+
+#define BP_POOL_MASK         0x7 
+
+#define BP_CONTIGUOUS                  (1 << 3)
+#define BP_PARAMBUFFER                 (1 << 4)
+
+#define BM_MAX_DEVMEM_ARENAS  2
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE                    *psDeviceNode,
+                                IMG_DEV_PHYADDR                        *psPDDevPAddr,
+                                PVRSRV_PER_PROCESS_DATA        *psPerProc,
+                                IMG_BOOL                                       *pbCreated);
+
+
+PVRSRV_ERROR
+BM_DestroyContext (IMG_HANDLE hBMContext,
+                                       IMG_BOOL *pbCreated);
+
+
+IMG_HANDLE 
+BM_CreateHeap (IMG_HANDLE hBMContext,
+                               DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+
+IMG_VOID 
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap);
+
+
+IMG_BOOL 
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_BOOL
+BM_Alloc (IMG_HANDLE                   hDevMemHeap,
+                       IMG_DEV_VIRTADDR        *psDevVAddr,
+                       IMG_SIZE_T                      uSize,
+                       IMG_UINT32                      *pui32Flags,
+                       IMG_UINT32                      uDevVAddrAlignment,
+                       BM_HANDLE                       *phBuf);
+
+IMG_BOOL
+BM_Wrap (      IMG_HANDLE hDevMemHeap,
+                   IMG_SIZE_T ui32Size,
+                       IMG_SIZE_T ui32Offset,
+                       IMG_BOOL bPhysContig,
+                       IMG_SYS_PHYADDR *psSysAddr,
+                       IMG_VOID *pvCPUVAddr,
+                       IMG_UINT32 *pui32Flags,
+                       BM_HANDLE *phBuf);
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf, 
+               IMG_UINT32 ui32Flags);
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf);
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf);
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf);
+
+IMG_HANDLE
+BM_HandleToOSMemHandle (BM_HANDLE hBuf);
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                               IMG_DEV_VIRTADDR sDevVPageAddr,
+                                                               IMG_DEV_PHYADDR *psDevPAddr);
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap);
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext);
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap);
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext);
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_VOID BM_Export(BM_HANDLE hBuf);
+
+IMG_VOID BM_FreeExport(BM_HANDLE hBuf, IMG_UINT32 ui32Flags);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/device.h b/drivers/staging/mrst/pvr/services4/srvkm/include/device.h
new file mode 100644 (file)
index 0000000..d2ff28b
--- /dev/null
@@ -0,0 +1,323 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __DEVICE_H__
+#define __DEVICE_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesint.h"
+#include "ra.h"                
+#include "resman.h"            
+
+typedef struct _BM_CONTEXT_ BM_CONTEXT;
+
+typedef struct _MMU_HEAP_ MMU_HEAP;
+typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+
+#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG              (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG   (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG            (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+
+typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
+#define DEVICE_MEMORY_HEAP_PERCONTEXT          0
+#define DEVICE_MEMORY_HEAP_KERNEL                      1
+#define DEVICE_MEMORY_HEAP_SHARED                      2
+#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED     3
+
+#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY 1
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV   2       
+
+typedef struct _DEVICE_MEMORY_HEAP_INFO_
+{
+       
+       IMG_UINT32                              ui32HeapID;
+
+       
+       IMG_CHAR                                *pszName;
+
+       
+       IMG_CHAR                                *pszBSName;
+       
+       
+       IMG_DEV_VIRTADDR                sDevVAddrBase;
+
+       
+       IMG_UINT32                              ui32HeapSize;
+
+       
+       IMG_UINT32                              ui32Attribs;
+
+       
+       DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+       
+       
+       IMG_HANDLE                              hDevMemHeap;
+       
+       
+       RA_ARENA                                *psLocalDevMemArena;
+
+       
+       IMG_UINT32                              ui32DataPageSize;
+
+       IMG_UINT32                              ui32XTileStride;
+
+} DEVICE_MEMORY_HEAP_INFO;
+
+typedef struct _DEVICE_MEMORY_INFO_
+{
+       
+       IMG_UINT32                              ui32AddressSpaceSizeLog2;
+
+       
+
+
+       IMG_UINT32                              ui32Flags;
+
+       
+       IMG_UINT32                              ui32HeapCount;
+       
+       
+       IMG_UINT32                              ui32SyncHeapID;
+       
+       
+       IMG_UINT32                              ui32MappingHeapID;
+
+       
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+       
+    BM_CONTEXT                         *pBMKernelContext;
+
+       
+    BM_CONTEXT                         *pBMContext;
+
+} DEVICE_MEMORY_INFO;
+
+
+typedef struct DEV_ARENA_DESCRIPTOR_TAG
+{
+       IMG_UINT32                              ui32HeapID;             
+
+       IMG_CHAR                                *pszName;               
+
+       IMG_DEV_VIRTADDR                BaseDevVAddr;   
+
+       IMG_UINT32                              ui32Size;               
+
+       DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+
+       
+       IMG_UINT32                              ui32DataPageSize;
+
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeapInfo;
+
+} DEV_ARENA_DESCRIPTOR;
+
+
+typedef struct _PDUMP_MMU_ATTRIB_
+{
+       PVRSRV_DEVICE_IDENTIFIER        sDevId;
+       
+       IMG_CHAR        *pszPDRegRegion;
+       
+       
+       IMG_UINT32 ui32DataPageMask;
+
+       
+       IMG_UINT32 ui32PTEValid;
+       IMG_UINT32 ui32PTSize;
+       IMG_UINT32 ui32PTEAlignShift;
+
+       
+       IMG_UINT32 ui32PDEMask;
+       IMG_UINT32 ui32PDEAlignShift;
+
+} PDUMP_MMU_ATTRIB;
+
+typedef struct _SYS_DATA_TAG_ *PSYS_DATA;
+
+typedef struct _PVRSRV_DEVICE_NODE_
+{
+       PVRSRV_DEVICE_IDENTIFIER        sDevId;
+       IMG_UINT32                                      ui32RefCount;
+
+       
+
+       
+       PVRSRV_ERROR                    (*pfnInitDevice) (IMG_VOID*);
+       
+       PVRSRV_ERROR                    (*pfnDeInitDevice) (IMG_VOID*);
+
+       
+       PVRSRV_ERROR                    (*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
+
+       
+       PVRSRV_ERROR                    (*pfnMMUInitialise)(struct _PVRSRV_DEVICE_NODE_*, MMU_CONTEXT**, IMG_DEV_PHYADDR*);
+       IMG_VOID                                (*pfnMMUFinalise)(MMU_CONTEXT*);
+       IMG_VOID                                (*pfnMMUInsertHeap)(MMU_CONTEXT*, MMU_HEAP*);
+       MMU_HEAP*                               (*pfnMMUCreate)(MMU_CONTEXT*,DEV_ARENA_DESCRIPTOR*,RA_ARENA**,PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+       IMG_VOID                                (*pfnMMUDelete)(MMU_HEAP*);
+       IMG_BOOL                                (*pfnMMUAlloc)(MMU_HEAP*pMMU,
+                                                                                  IMG_SIZE_T uSize,
+                                                                                  IMG_SIZE_T *pActualSize,
+                                                                                  IMG_UINT32 uFlags,
+                                                                                  IMG_UINT32 uDevVAddrAlignment,
+                                                                                  IMG_DEV_VIRTADDR *pDevVAddr);
+       IMG_VOID                                (*pfnMMUFree)(MMU_HEAP*,IMG_DEV_VIRTADDR,IMG_UINT32);
+       IMG_VOID                                (*pfnMMUEnable)(MMU_HEAP*);
+       IMG_VOID                                (*pfnMMUDisable)(MMU_HEAP*);
+       IMG_VOID                                (*pfnMMUMapPages)(MMU_HEAP *pMMU,
+                                                                                         IMG_DEV_VIRTADDR devVAddr,
+                                                                                         IMG_SYS_PHYADDR SysPAddr,
+                                                                                         IMG_SIZE_T uSize,
+                                                                                         IMG_UINT32 ui32MemFlags,
+                                                                                         IMG_HANDLE hUniqueTag);
+       IMG_VOID                                (*pfnMMUMapShadow)(MMU_HEAP            *pMMU,
+                                                                                          IMG_DEV_VIRTADDR    MapBaseDevVAddr,
+                                                                                          IMG_SIZE_T          uSize, 
+                                                                                          IMG_CPU_VIRTADDR    CpuVAddr,
+                                                                                          IMG_HANDLE          hOSMemHandle,
+                                                                                          IMG_DEV_VIRTADDR    *pDevVAddr,
+                                                                                          IMG_UINT32 ui32MemFlags,
+                                                                                          IMG_HANDLE hUniqueTag);
+       IMG_VOID                                (*pfnMMUUnmapPages)(MMU_HEAP *pMMU,
+                                                                                               IMG_DEV_VIRTADDR dev_vaddr,
+                                                                                               IMG_UINT32 ui32PageCount,
+                                                                                               IMG_HANDLE hUniqueTag);
+
+       IMG_VOID                                (*pfnMMUMapScatter)(MMU_HEAP *pMMU,
+                                                                                               IMG_DEV_VIRTADDR DevVAddr,
+                                                                                               IMG_SYS_PHYADDR *psSysAddr,
+                                                                                               IMG_SIZE_T uSize,
+                                                                                               IMG_UINT32 ui32MemFlags,
+                                                                                               IMG_HANDLE hUniqueTag);
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+       IMG_BOOL                                (*pfnMMUIsHeapShared)(MMU_HEAP *);
+#endif
+       IMG_DEV_PHYADDR                 (*pfnMMUGetPhysPageAddr)(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+       IMG_DEV_PHYADDR                 (*pfnMMUGetPDDevPAddr)(MMU_CONTEXT *pMMUContext);
+
+       
+       PVRSRV_ERROR                    (*pfnAllocMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+                                                                                                               PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                                                                               IMG_UINT32 ui32TilingStride,
+                                                                                                               IMG_UINT32 *pui32RangeIndex);
+       PVRSRV_ERROR                    (*pfnFreeMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+                                                                                                               IMG_UINT32 ui32RangeIndex);
+
+       
+       IMG_BOOL                                (*pfnDeviceISR)(IMG_VOID*);
+       
+       IMG_VOID                                *pvISRData;
+       
+       IMG_UINT32                              ui32SOCInterruptBit;
+       
+       IMG_VOID                                (*pfnDeviceMISR)(IMG_VOID*);
+
+       
+       IMG_VOID                                (*pfnDeviceCommandComplete)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+       
+       IMG_BOOL                                bReProcessDeviceCommandComplete;
+       
+       
+       DEVICE_MEMORY_INFO              sDevMemoryInfo;
+
+       
+       IMG_VOID                                *pvDevice;
+       IMG_UINT32                              ui32pvDeviceSize; 
+               
+       
+       PRESMAN_CONTEXT                 hResManContext;
+       
+       
+       PSYS_DATA                               psSysData;
+       
+       
+       RA_ARENA                                *psLocalDevMemArena;
+       
+       IMG_UINT32                              ui32Flags;
+       
+       struct _PVRSRV_DEVICE_NODE_     *psNext;
+       struct _PVRSRV_DEVICE_NODE_     **ppsThis;
+#if defined(PVRSRV_RESOURCE_PROFILING)
+       PVRSRV_ERROR                     (*pfnResProfCB)(IMG_VOID  *psDeviceNode, IMG_UINT32 ui32AllocedMem, IMG_BOOL bAlloc);
+#endif
+
+#if defined(PDUMP)
+       
+       PVRSRV_ERROR                    (*pfnPDumpInitDevice)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+       
+       IMG_UINT32                              (*pfnMMUGetContextID)(IMG_HANDLE hDevMemContext);
+#endif
+} PVRSRV_DEVICE_NODE;
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+                                                                                         PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+                                                                                         IMG_UINT32 ui32SOCInterruptBit,
+                                                                                         IMG_UINT32 *pui32DeviceIndex );
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice(IMG_UINT32 ui32DevIndex);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex);
+
+#if !defined(USE_CODE)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
+                                                                                                  IMG_UINT32 ui32Value,
+                                                                                                  IMG_UINT32 ui32Mask,
+                                                                                                       IMG_UINT32                              ui32Timeoutus,
+                                                                                                       IMG_UINT32                              ui32PollPeriodus,
+                                                                                                       IMG_BOOL                                bAllowPreemption);
+
+#endif 
+
+
+#if defined (USING_ISR_INTERRUPTS)
+PVRSRV_ERROR IMG_CALLCONV PollForInterruptKM(IMG_UINT32 ui32Value,
+                                                               IMG_UINT32 ui32Mask,
+                                                               IMG_UINT32 ui32Waitus,
+                                                               IMG_UINT32 ui32Tries);
+#endif 
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData);
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData);
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData);
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData);
+
+#if defined(__cplusplus)
+}
+#endif
+       
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/handle.h b/drivers/staging/mrst/pvr/services4/srvkm/include/handle.h
new file mode 100644 (file)
index 0000000..56de04a
--- /dev/null
@@ -0,0 +1,383 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "hash.h"
+#include "resman.h"
+
+typedef enum
+{
+       PVRSRV_HANDLE_TYPE_NONE = 0,
+       PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+       PVRSRV_HANDLE_TYPE_DEV_NODE,
+       PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+       PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+       PVRSRV_HANDLE_TYPE_MEM_INFO,
+       PVRSRV_HANDLE_TYPE_SYNC_INFO,
+       PVRSRV_HANDLE_TYPE_DISP_INFO,
+       PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+       PVRSRV_HANDLE_TYPE_BUF_INFO,
+       PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+       PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+       PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+       PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+       PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+       PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+       PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+       PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+       PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+       PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+       PVRSRV_HANDLE_TYPE_MMAP_INFO,
+       PVRSRV_HANDLE_TYPE_SOC_TIMER,
+       PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ
+} PVRSRV_HANDLE_TYPE;
+
+typedef enum
+{
+       
+       PVRSRV_HANDLE_ALLOC_FLAG_NONE =                 0,
+       
+       PVRSRV_HANDLE_ALLOC_FLAG_SHARED =               0x01,
+       
+       PVRSRV_HANDLE_ALLOC_FLAG_MULTI =                0x02,
+       
+       PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE =              0x04
+} PVRSRV_HANDLE_ALLOC_FLAG;
+
+struct _PVRSRV_HANDLE_BASE_;
+typedef struct _PVRSRV_HANDLE_BASE_ PVRSRV_HANDLE_BASE;
+
+#ifdef PVR_SECURE_HANDLES
+extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+#define        KERNEL_HANDLE_BASE (gpsKernelHandleBase)
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize);
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle);
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase);
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID);
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
+
+#else  
+
+#define KERNEL_HANDLE_BASE IMG_NULL
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+       PVR_UNREFERENCED_PARAMETER(eType);
+       PVR_UNREFERENCED_PARAMETER(eFlag);
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       *phHandle = pvData;
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+       PVR_UNREFERENCED_PARAMETER(eType);
+       PVR_UNREFERENCED_PARAMETER(eFlag);
+       PVR_UNREFERENCED_PARAMETER(hParent);
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       *phHandle = pvData;
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+       PVR_UNREFERENCED_PARAMETER(eType);
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       *phHandle = pvData;
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandleAnyType)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+       
+       *peType = PVRSRV_HANDLE_TYPE_NONE;
+
+       *ppvData = hHandle;
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+       PVR_UNREFERENCED_PARAMETER(eType);
+
+       *ppvData = hHandle;
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+       PVR_UNREFERENCED_PARAMETER(eType);
+       PVR_UNREFERENCED_PARAMETER(hAncestor);
+
+       *ppvData = hHandle;
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetParentHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+       PVR_UNREFERENCED_PARAMETER(eType);
+       PVR_UNREFERENCED_PARAMETER(hHandle);
+
+       *phParent = IMG_NULL;
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupAndReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       PVR_UNREFERENCED_PARAMETER(eType);
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       *ppvData = hHandle;
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+       PVR_UNREFERENCED_PARAMETER(hHandle);
+       PVR_UNREFERENCED_PARAMETER(eType);
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVNewHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+       PVR_UNREFERENCED_PARAMETER(ui32BatchSize);
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCommitHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandleBatch)
+#endif
+static INLINE
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSetMaxHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+       PVR_UNREFERENCED_PARAMETER(ui32MaxHandle);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetMaxHandle)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       return 0;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVEnableHandlePurging)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPurgeHandles)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+       *ppsBase = IMG_NULL;
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFreeHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+       PVR_UNREFERENCED_PARAMETER(psBase);
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleDeInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+       return PVRSRV_OK;
+}
+
+#endif 
+
+#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
+       (IMG_VOID)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
+
+#define PVRSRVAllocSubHandleNR(psBase, phHandle, pvData, eType, eFlag, hParent) \
+       (IMG_VOID)PVRSRVAllocSubHandle(psBase, phHandle, pvData, eType, eFlag, hParent)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/hash.h b/drivers/staging/mrst/pvr/services4/srvkm/include/hash.h
new file mode 100644 (file)
index 0000000..d45f4a9
--- /dev/null
@@ -0,0 +1,73 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#include "img_types.h"
+#include "osfunc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef IMG_UINT32 HASH_FUNC(IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+typedef IMG_BOOL HASH_KEY_COMP(IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+typedef struct _HASH_TABLE_ HASH_TABLE;
+
+IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+
+IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+
+IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+
+IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+
+IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+
+IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+#ifdef HASH_TRACE
+IMG_VOID HASH_Dump (HASH_TABLE *pHash);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/lists.h b/drivers/staging/mrst/pvr/services4/srvkm/include/lists.h
new file mode 100644 (file)
index 0000000..6fa9ea7
--- /dev/null
@@ -0,0 +1,271 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __LISTS_UTILS__
+#define __LISTS_UTILS__
+
+#include <stdarg.h>
+#include "img_types.h"
+
+#define DECLARE_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))\
+{\
+       while(psHead)\
+       {\
+               pfnCallBack(psHead);\
+               psHead = psHead->psNext;\
+       }\
+}
+
+
+#define DECLARE_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...) \
+{\
+       va_list ap;\
+       while(psHead)\
+       {\
+               va_start(ap, pfnCallBack);\
+               pfnCallBack(psHead, ap);\
+               psHead = psHead->psNext;\
+               va_end(ap);\
+       }\
+}
+
+
+#define DECLARE_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))\
+{ \
+       IMG_VOID *pResult;\
+       TYPE *psNextNode;\
+       pResult = IMG_NULL;\
+       psNextNode = psHead;\
+       while(psHead && !pResult)\
+       {\
+               psNextNode = psNextNode->psNext;\
+               pResult = pfnCallBack(psHead);\
+               psHead = psNextNode;\
+       }\
+       return pResult;\
+}
+
+
+#define DECLARE_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+       va_list ap;\
+       TYPE *psNextNode;\
+       IMG_VOID* pResult = IMG_NULL;\
+       while(psHead && !pResult)\
+       {\
+               psNextNode = psHead->psNext;\
+               va_start(ap, pfnCallBack);\
+               pResult = pfnCallBack(psHead, ap);\
+               va_end(ap);\
+               psHead = psNextNode;\
+       }\
+       return pResult;\
+}
+
+#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))\
+{ \
+       RTYPE result;\
+       TYPE *psNextNode;\
+       result = CONTINUE;\
+       psNextNode = psHead;\
+       while(psHead && result == CONTINUE)\
+       {\
+               psNextNode = psNextNode->psNext;\
+               result = pfnCallBack(psHead);\
+               psHead = psNextNode;\
+       }\
+       return result;\
+}
+
+
+#define DECLARE_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+       va_list ap;\
+       TYPE *psNextNode;\
+       RTYPE result = CONTINUE;\
+       while(psHead && result == CONTINUE)\
+       {\
+               psNextNode = psHead->psNext;\
+               va_start(ap, pfnCallBack);\
+               result = pfnCallBack(psHead, ap);\
+               va_end(ap);\
+               psHead = psNextNode;\
+       }\
+       return result;\
+}
+
+
+#define DECLARE_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
+
+#define IMPLEMENT_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)\
+{\
+       (*psNode->ppsThis)=psNode->psNext;\
+       if(psNode->psNext)\
+       {\
+               psNode->psNext->ppsThis = psNode->ppsThis;\
+       }\
+}
+
+#define DECLARE_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
+
+#define IMPLEMENT_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)\
+{\
+       psNewNode->ppsThis = ppsHead;\
+       psNewNode->psNext = *ppsHead;\
+       *ppsHead = psNewNode;\
+       if(psNewNode->psNext)\
+       {\
+               psNewNode->psNext->ppsThis = &(psNewNode->psNext);\
+       }\
+}
+
+#define DECLARE_LIST_FIND(TYPE) \
+IMG_VOID* List_##TYPE##_Find(TYPE *psHead, TYPE *psNode)
+
+#define IMPLEMENT_LIST_FIND(TYPE) \
+IMG_VOID* List_##TYPE##_Find(TYPE *psHead, TYPE *psNode)\
+{\
+       while (psHead)\
+       {\
+               if (psHead == psNode) \
+               {\
+                       break;\
+               }\
+               psHead = psHead->psNext;\
+       }\
+       return psHead;\
+}
+
+#define DECLARE_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)
+
+#define IMPLEMENT_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)\
+{\
+    TYPE *psTmpNode1; \
+    TYPE *psTmpNode2; \
+    TYPE *psCurNode; \
+       psTmpNode1 = IMG_NULL; \
+       psCurNode = *ppsHead; \
+       while(psCurNode) { \
+       psTmpNode2 = psCurNode->psNext; \
+        psCurNode->psNext = psTmpNode1; \
+               psTmpNode1 = psCurNode; \
+               psCurNode = psTmpNode2; \
+               if(psCurNode) \
+               { \
+                       psTmpNode1->ppsThis = &(psCurNode->psNext); \
+               } \
+               else \
+               { \
+                       psTmpNode1->ppsThis = ppsHead;          \
+               } \
+       } \
+       *ppsHead = psTmpNode1; \
+}
+
+#define IS_LAST_ELEMENT(x) ((x)->psNext == IMG_NULL)
+
+#include "services_headers.h"
+
+DECLARE_LIST_ANY_VA(BM_HEAP);
+DECLARE_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+DECLARE_LIST_REMOVE(BM_HEAP);
+DECLARE_LIST_INSERT(BM_HEAP);
+DECLARE_LIST_FIND(BM_HEAP);
+
+DECLARE_LIST_ANY_VA(BM_CONTEXT);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(BM_CONTEXT);
+DECLARE_LIST_REMOVE(BM_CONTEXT);
+DECLARE_LIST_INSERT(BM_CONTEXT);
+DECLARE_LIST_FIND(BM_CONTEXT);
+
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FIND(PVRSRV_DEVICE_NODE);
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
+DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
+
+#if defined(PERPROC_LIST)
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_PER_PROCESS_DATA);
+DECLARE_LIST_INSERT(PVRSRV_PER_PROCESS_DATA);
+DECLARE_LIST_REMOVE(PVRSRV_PER_PROCESS_DATA);
+#endif
+
+#undef DECLARE_LIST_ANY_2
+#undef DECLARE_LIST_ANY_VA
+#undef DECLARE_LIST_ANY_VA_2
+#undef DECLARE_LIST_FOR_EACH
+#undef DECLARE_LIST_FOR_EACH_VA
+#undef DECLARE_LIST_INSERT
+#undef DECLARE_LIST_REMOVE
+#undef DECLARE_LIST_FIND
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/metrics.h b/drivers/staging/mrst/pvr/services4/srvkm/include/metrics.h
new file mode 100644 (file)
index 0000000..2632f8d
--- /dev/null
@@ -0,0 +1,130 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _METRICS_
+#define _METRICS_
+
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(DEBUG) || defined(TIMING)
+
+
+typedef struct 
+{
+       IMG_UINT32 ui32Start;
+       IMG_UINT32 ui32Stop;
+       IMG_UINT32 ui32Total;
+       IMG_UINT32 ui32Count;
+} Temporal_Data;
+
+extern Temporal_Data asTimers[]; 
+
+extern IMG_UINT32 PVRSRVTimeNow(IMG_VOID);
+extern IMG_VOID   PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo);
+extern IMG_VOID   PVRSRVOutputMetricTotals(IMG_VOID);
+
+
+#define PVRSRV_TIMER_DUMMY                             0
+
+#define PVRSRV_TIMER_EXAMPLE_1                 1
+#define PVRSRV_TIMER_EXAMPLE_2                 2
+
+
+#define PVRSRV_NUM_TIMERS              (PVRSRV_TIMER_EXAMPLE_2 + 1)
+
+#define PVRSRV_TIME_START(X)   { \
+                                                                       asTimers[X].ui32Count += 1; \
+                                                                       asTimers[X].ui32Count |= 0x80000000L; \
+                                                                       asTimers[X].ui32Start = PVRSRVTimeNow(); \
+                                                                       asTimers[X].ui32Stop  = 0; \
+                                                               }
+
+#define PVRSRV_TIME_SUSPEND(X) { \
+                                                                       asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+                                                               }
+
+#define PVRSRV_TIME_RESUME(X)  { \
+                                                                       asTimers[X].ui32Start = PVRSRVTimeNow(); \
+                                                               }
+
+#define PVRSRV_TIME_STOP(X)            { \
+                                                                       asTimers[X].ui32Stop  += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+                                                                       asTimers[X].ui32Total += asTimers[X].ui32Stop; \
+                                                                       asTimers[X].ui32Count &= 0x7FFFFFFFL; \
+                                                               }
+
+#define PVRSRV_TIME_RESET(X)   { \
+                                                                       asTimers[X].ui32Start = 0; \
+                                                                       asTimers[X].ui32Stop  = 0; \
+                                                                       asTimers[X].ui32Total = 0; \
+                                                                       asTimers[X].ui32Count = 0; \
+                                                               }
+
+
+#if defined(__sh__)
+
+#define TST_REG   ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM))        
+
+#define TCOR_2    ((volatile IMG_UINT *)  (psDevInfo->pvSOCRegsBaseKM+28))     
+#define TCNT_2    ((volatile IMG_UINT *)  (psDevInfo->pvSOCRegsBaseKM+32))     
+#define TCR_2     ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36))     
+
+#define TIMER_DIVISOR  4
+
+#endif 
+
+
+
+
+
+#else 
+
+
+
+#define PVRSRV_TIME_START(X)
+#define PVRSRV_TIME_SUSPEND(X)
+#define PVRSRV_TIME_RESUME(X)
+#define PVRSRV_TIME_STOP(X)
+#define PVRSRV_TIME_RESET(X)
+
+#define PVRSRVSetupMetricTimers(X)
+#define PVRSRVOutputMetricTotals()
+
+
+
+#endif 
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/osfunc.h b/drivers/staging/mrst/pvr/services4/srvkm/include/osfunc.h
new file mode 100644 (file)
index 0000000..314cd63
--- /dev/null
@@ -0,0 +1,586 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG          1
+#endif
+
+#ifndef __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/hardirq.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#if defined(__arm__)
+#include <asm/memory.h>
+#endif
+#endif
+
+#include "services.h"
+
+       
+       #define PVRSRV_PAGEABLE_SELECT          PVRSRV_OS_PAGEABLE_HEAP
+
+#define KERNEL_ID                      0xffffffffL
+#define POWER_MANAGER_ID       0xfffffffeL
+#define ISR_ID                         0xfffffffdL
+#define TIMER_ID                       0xfffffffcL
+
+
+#define HOST_PAGESIZE                  OSGetPageSize
+#define HOST_PAGEMASK                  (HOST_PAGESIZE()-1)
+#define HOST_PAGEALIGN(addr)   (((addr) + HOST_PAGEMASK) & ~HOST_PAGEMASK)
+
+#define PVRSRV_OS_HEAP_MASK                    0xf 
+#define PVRSRV_OS_PAGEABLE_HEAP                0x1 
+#define PVRSRV_OS_NON_PAGEABLE_HEAP    0x2 
+
+
+IMG_UINT32 OSClockus(IMG_VOID);
+IMG_SIZE_T OSGetPageSize(IMG_VOID);
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+                                                                IMG_UINT32 ui32Irq,
+                                                                IMG_CHAR *pszISRName,
+                                                                IMG_VOID *pvDeviceNode);
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq);
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData);
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE, IMG_VOID* pvLinAddr);
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE *phOSMemHandle);
+IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnReservePhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID);
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID);
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                               IMG_VOID *pvRangeAddrStart,
+                                                               IMG_UINT32 ui32Length);
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                               IMG_VOID *pvRangeAddrStart,
+                                                               IMG_UINT32 ui32Length);
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                                        IMG_VOID *pvRangeAddrStart,
+                                                                        IMG_UINT32 ui32Length);
+
+#else 
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSFlushCPUCacheKM)
+#endif
+static INLINE IMG_VOID OSFlushCPUCacheKM(IMG_VOID) {}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSCleanCPUCacheKM)
+#endif
+static INLINE IMG_VOID OSCleanCPUCacheKM(IMG_VOID) {}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSFlushCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                                                         IMG_VOID *pvRangeAddrStart,
+                                                                                         IMG_UINT32 ui32Length)
+{
+       PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+       PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+       PVR_UNREFERENCED_PARAMETER(ui32Length);
+       return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSCleanCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                                                         IMG_VOID *pvRangeAddrStart,
+                                                                                         IMG_UINT32 ui32Length)
+{
+       PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+       PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+       PVR_UNREFERENCED_PARAMETER(ui32Length);
+       return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSInvalidateCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                                                                  IMG_VOID *pvRangeAddrStart,
+                                                                                                  IMG_UINT32 ui32Length)
+{
+       PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+       PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+       PVR_UNREFERENCED_PARAMETER(ui32Length);
+       return IMG_FALSE;
+}
+
+#endif 
+
+#if defined(__linux__)
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+                                                                       IMG_VOID *pvCpuVAddr, 
+                                                                       IMG_SIZE_T ui32Bytes,
+                                                                       IMG_UINT32 ui32Flags, 
+                                                                       IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+                                                                       IMG_SIZE_T ui32Bytes,
+                                                                       IMG_UINT32 ui32Flags,
+                                                                       IMG_HANDLE hOSMemHandle);
+#else  
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+                                                                                                       IMG_VOID *pvCpuVAddr,
+                                                                                                       IMG_SIZE_T ui32Bytes,
+                                                                                                       IMG_UINT32 ui32Flags,
+                                                                                                       IMG_HANDLE *phOSMemHandle)
+{
+       PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+       PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+       PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+       PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+                                                                                                       IMG_SIZE_T ui32Bytes,
+                                                                                                       IMG_UINT32 ui32Flags,
+                                                                                                       IMG_HANDLE hOSMemHandle)
+{
+       PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+       PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+       PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif 
+
+
+#if defined(__linux__)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+#if defined(__linux__) 
+       *ppvCpuVAddr = IMG_NULL;
+       return OSRegisterDiscontigMem(pBasePAddr, *ppvCpuVAddr, ui32Bytes, ui32Flags, phOSMemHandle);   
+#else
+       extern IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(IMG_SYS_PHYADDR SysPAddr);
+
+       
+       return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, ppvCpuVAddr, phOSMemHandle);
+#endif 
+}
+
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+#if defined(__linux__)
+       OSUnRegisterDiscontigMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+#endif
+       
+       return PVRSRV_OK;
+}
+#else  
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+       PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+       PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+       PVR_UNREFERENCED_PARAMETER(ppvCpuVAddr);
+       PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+       PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+       PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+       PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif 
+
+PVRSRV_ERROR OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+                                                       IMG_VOID *pvCpuVAddr,
+                                                       IMG_SIZE_T ui32Bytes,
+                                                       IMG_UINT32 ui32Flags,
+                                                       IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterMem(IMG_VOID *pvCpuVAddr,
+                                                       IMG_SIZE_T ui32Bytes,
+                                                       IMG_UINT32 ui32Flags,
+                                                       IMG_HANDLE hOSMemHandle);
+
+
+
+#if defined(__linux__)
+PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+                                                          IMG_UINTPTR_T ui32ByteOffset,
+                                                          IMG_SIZE_T ui32Bytes,
+                                                          IMG_UINT32 ui32Flags,
+                                                          IMG_HANDLE *phOSMemHandleRet);
+PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetSubMemHandle)
+#endif
+static INLINE PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+                                                                                        IMG_UINTPTR_T ui32ByteOffset,
+                                                                                        IMG_SIZE_T ui32Bytes,
+                                                                                        IMG_UINT32 ui32Flags,
+                                                                                        IMG_HANDLE *phOSMemHandleRet)
+{
+       PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+       PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+       *phOSMemHandleRet = hOSMemHandle;
+       return PVRSRV_OK;
+}
+
+static INLINE PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+       PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+       return PVRSRV_OK;
+}
+#endif
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID);
+IMG_UINTPTR_T OSGetCurrentThreadID( IMG_VOID );
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
+PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+       #define OSAllocMem(flags, size, linAddr, blockAlloc, logStr) \
+               (PVR_TRACE(("OSAllocMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): " logStr " (size = 0x%lx)", size)), \
+                       OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+
+       #define OSAllocPages(flags, size, pageSize, linAddr, pageAlloc) \
+               (PVR_TRACE(("OSAllocPages(" #flags ", " #size ", " #pageSize ", " #linAddr ", " #pageAlloc "): (size = 0x%lx)", size)), \
+                       OSAllocPages_Impl(flags, size, pageSize, linAddr, pageAlloc))
+               
+       #define OSFreeMem(flags, size, linAddr, blockAlloc) \
+               (PVR_TRACE(("OSFreeMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): (pointer = 0x%X)", linAddr)), \
+                       OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+#else
+       #define OSAllocMem(flags, size, linAddr, blockAlloc, logString) \
+               OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+       
+       #define OSAllocPages OSAllocPages_Impl
+       
+       #define OSFreeMem(flags, size, linAddr, blockAlloc) \
+                       OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+#endif
+#ifdef PVRSRV_DEBUG_OS_MEMORY
+
+       PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+                                                                               IMG_UINT32 ui32Size,
+                                                                               IMG_PVOID *ppvCpuVAddr,
+                                                                               IMG_HANDLE *phBlockAlloc,
+                                                                               IMG_CHAR *pszFilename,
+                                                                               IMG_UINT32 ui32Line);
+       
+       PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+                                                                        IMG_UINT32 ui32Size,
+                                                                        IMG_PVOID pvCpuVAddr,
+                                                                        IMG_HANDLE hBlockAlloc,
+                                                                        IMG_CHAR *pszFilename,
+                                                                        IMG_UINT32 ui32Line);
+
+
+       typedef struct
+       {       
+               IMG_UINT8 sGuardRegionBefore[8];
+               IMG_CHAR sFileName[128];
+               IMG_UINT32 uLineNo;
+               IMG_SIZE_T uSize;
+               IMG_SIZE_T uSizeParityCheck;
+               enum valid_tag
+               {       isFree = 0x277260FF,
+                       isAllocated = 0x260511AA
+               } eValid;
+       } OSMEM_DEBUG_INFO;
+       
+       #define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO)) 
+       #define TEST_BUFFER_PADDING_AFTER  (8) 
+       #define TEST_BUFFER_PADDING (TEST_BUFFER_PADDING_STATUS + TEST_BUFFER_PADDING_AFTER)
+#else
+       #define OSAllocMem_Debug_Wrapper OSAllocMem_Debug_Linux_Memory_Allocations
+       #define OSFreeMem_Debug_Wrapper OSFreeMem_Debug_Linux_Memory_Allocations
+#endif
+#if defined(__linux__) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+       PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+       
+       #define OSAllocMem_Debug_Linux_Memory_Allocations OSAllocMem_Impl
+       #define OSFreeMem_Debug_Linux_Memory_Allocations OSFreeMem_Impl
+#else
+       PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc);
+       PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc);
+       
+       #define OSAllocMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+               OSAllocMem_Impl(flags, size, addr, blockAlloc)
+       #define OSFreeMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+               OSFreeMem_Impl(flags, size, addr, blockAlloc)
+#endif
+
+
+#if defined(__linux__)
+IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_SIZE_T ui32ByteOffset);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleToCpuPAddr)
+#endif
+static INLINE IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_HANDLE hOSMemHandle, IMG_SIZE_T ui32ByteOffset)
+{
+       IMG_CPU_PHYADDR sCpuPAddr;
+       PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+       PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+       sCpuPAddr.uiAddr = 0;
+       return sCpuPAddr;
+}
+#endif
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData);
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData);
+IMG_CHAR* OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc);
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T ui32Size, const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+#define OSStringLength(pszString) strlen(pszString)
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName,
+                                                                PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+                                                                                       IMG_HANDLE *phOSEvent);
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+                                                                                       IMG_HANDLE hOSEventKM);
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr);
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr);
+
+IMG_PVOID MapUserFromKernel(IMG_PVOID pvLinAddrKM,IMG_SIZE_T ui32Size,IMG_HANDLE *phMemBlock);
+IMG_PVOID OSMapHWRegsIntoUserSpace(IMG_HANDLE hDevCookie, IMG_SYS_PHYADDR sRegAddr, IMG_UINT32 ulSize, IMG_PVOID *ppvProcess);
+IMG_VOID  OSUnmapHWRegsFromUserSpace(IMG_HANDLE hDevCookie, IMG_PVOID pvUserAddr, IMG_PVOID pvProcess);
+
+IMG_VOID  UnmapUserFromKernel(IMG_PVOID pvLinAddrUM, IMG_SIZE_T ui32Size, IMG_HANDLE hMemBlock);
+
+PVRSRV_ERROR OSMapPhysToUserSpace(IMG_HANDLE hDevCookie,
+                                                                 IMG_SYS_PHYADDR sCPUPhysAddr,
+                                                                 IMG_SIZE_T uiSizeInBytes,
+                                                                 IMG_UINT32 ui32CacheFlags,
+                                                                 IMG_PVOID *ppvUserAddr,
+                                                                 IMG_SIZE_T *puiActualSize,
+                                                                 IMG_HANDLE hMappingHandle);
+
+PVRSRV_ERROR OSUnmapPhysToUserSpace(IMG_HANDLE hDevCookie,
+                                                                       IMG_PVOID pvUserAddr,
+                                                                       IMG_PVOID pvProcess);
+
+PVRSRV_ERROR OSLockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSUnlockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_BOOL OSIsResourceLocked(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource);
+PVRSRV_ERROR OSDestroyResource(PVRSRV_RESOURCE *psResource);
+IMG_VOID OSBreakResourceLock(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems);
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID);
+IMG_UINT32 OSPCIReadDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg);
+IMG_VOID OSPCIWriteDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg, IMG_UINT32 ui32Value);
+
+#ifndef OSReadHWReg
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+#endif
+#ifndef OSWriteHWReg
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+#endif
+
+typedef IMG_VOID (*PFN_TIMER_FUNC)(IMG_VOID*);
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout);
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer);
+
+PVRSRV_ERROR OSGetSysMemSize(IMG_SIZE_T *pui32Bytes);
+
+typedef enum _HOST_PCI_INIT_FLAGS_
+{
+       HOST_PCI_INIT_FLAG_BUS_MASTER   = 0x00000001,
+       HOST_PCI_INIT_FLAG_MSI          = 0x00000002,
+       HOST_PCI_INIT_FLAG_FORCE_I32    = 0x7fffffff
+} HOST_PCI_INIT_FLAGS;
+
+struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_ *PVRSRV_PCI_DEV_HANDLE;
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ);
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData);
+
+IMG_VOID OSPanic(IMG_VOID);
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
+
+typedef enum _img_verify_test
+{
+       PVR_VERIFY_WRITE = 0,
+       PVR_VERIFY_READ
+} IMG_VERIFY_TEST;
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T ui32Bytes);
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+
+#if defined(__linux__)
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr, 
+                                                                       IMG_SIZE_T ui32Bytes, 
+                                                                       IMG_SYS_PHYADDR *psSysPAddr,
+                                                                       IMG_HANDLE *phOSWrapMem);
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSAcquirePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr, 
+                                                                                               IMG_SIZE_T ui32Bytes, 
+                                                                                               IMG_SYS_PHYADDR *psSysPAddr,
+                                                                                               IMG_HANDLE *phOSWrapMem)
+{
+       PVR_UNREFERENCED_PARAMETER(pvCPUVAddr);
+       PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+       PVR_UNREFERENCED_PARAMETER(psSysPAddr);
+       PVR_UNREFERENCED_PARAMETER(phOSWrapMem);
+       return PVRSRV_OK;       
+}
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleasePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+       PVR_UNREFERENCED_PARAMETER(hOSWrapMem);
+       return PVRSRV_OK;       
+}
+#endif
+                                                                       
+#if defined(__linux__) && defined(__KERNEL__)
+
+#define        OS_SUPPORTS_IN_LISR
+
+static inline IMG_BOOL OSInLISR(IMG_VOID unref__ *pvSysData)
+{
+       PVR_UNREFERENCED_PARAMETER(pvSysData);
+       return (in_irq()) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_VOID OSWriteMemoryBarrier(IMG_VOID)
+{
+       wmb();
+}
+
+static inline IMG_VOID OSMemoryBarrier(IMG_VOID)
+{
+       mb();
+}
+
+#else 
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSWriteMemoryBarrier)
+#endif
+static INLINE IMG_VOID OSWriteMemoryBarrier(IMG_VOID) { }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemoryBarrier)
+#endif
+static INLINE IMG_VOID OSMemoryBarrier(IMG_VOID) { }
+
+#endif 
+#ifdef PVRSRV_OS_MEM_INFO
+typedef struct
+{
+       IMG_UINT32 ui32TotalMem;
+       IMG_UINT32 ui32FreeMem;
+} PVRSRV_MEM_INFO;
+
+IMG_VOID OSGetMemoryInfo(PVRSRV_MEM_INFO * psMemInfo);
+#endif
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/osperproc.h b/drivers/staging/mrst/pvr/services4/srvkm/include/osperproc.h
new file mode 100644 (file)
index 0000000..80a912f
--- /dev/null
@@ -0,0 +1,76 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __OSPERPROC_H__
+#define __OSPERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData);
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+#else  
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+       PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataDeInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+       PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
+
+       return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessSetHandleOptions)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+       PVR_UNREFERENCED_PARAMETER(psHandleBase);
+
+       return PVRSRV_OK;
+}
+#endif 
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/ossync.h b/drivers/staging/mrst/pvr/services4/srvkm/include/ossync.h
new file mode 100644 (file)
index 0000000..544032b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,·
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+ *
+ */
+
+#ifndef _OSSYNC_H_
+#define _OSSYNC_H_
+
+#include "servicesint.h"
+
+#define PVRSRV_SYNC_READ       (1 << 0)
+#define PVRSRV_SYNC_WRITE      (1 << 1)
+
+int PVRSRVCallbackOnSync(PVRSRV_KERNEL_SYNC_INFO *sync_info, int flags,
+                         void (*callback)(void *), void *user_data);
+void PVRSRVCheckPendingSyncs(void);
+
+#endif /* _OSSYNC_H_ */
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/pdump_int.h b/drivers/staging/mrst/pvr/services4/srvkm/include/pdump_int.h
new file mode 100644 (file)
index 0000000..3c03888
--- /dev/null
@@ -0,0 +1,67 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __PDUMP_INT_H__
+#define __PDUMP_INT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined(_UITRON)
+#include "dbgdrvif.h"
+
+IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID);
+
+#endif 
+
+typedef enum
+{
+       
+       PDUMP_WRITE_MODE_CONTINUOUS = 0,
+       
+       PDUMP_WRITE_MODE_LASTFRAME,
+       
+       PDUMP_WRITE_MODE_BINCM,
+       
+       PDUMP_WRITE_MODE_PERSISTENT
+} PDUMP_DDWMODE;
+
+
+IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
+
+IMG_UINT32 PDumpOSDebugDriverWrite(    PDBG_STREAM psStream,
+                                                                       PDUMP_DDWMODE eDbgDrvWriteMode,
+                                                                       IMG_UINT8 *pui8Data,
+                                                                       IMG_UINT32 ui32BCount,
+                                                                       IMG_UINT32 ui32Level,
+                                                                       IMG_UINT32 ui32DbgDrvFlags);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/pdump_km.h b/drivers/staging/mrst/pvr/services4/srvkm/include/pdump_km.h
new file mode 100644 (file)
index 0000000..1be14d6
--- /dev/null
@@ -0,0 +1,406 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+
+#include "pdump_osfunc.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "pdump.h"
+
+#define PDUMP_PD_UNIQUETAG                     (IMG_HANDLE)0
+#define PDUMP_PT_UNIQUETAG                     (IMG_HANDLE)0
+
+#define PDUMP_STREAM_PARAM2                    0
+#define PDUMP_STREAM_SCRIPT2           1
+#define PDUMP_STREAM_DRIVERINFO                2
+#define PDUMP_NUM_STREAMS                      3
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+extern IMG_UINT32 g_ui32EveryLineCounter;
+#endif
+
+#ifndef PDUMP
+#define MAKEUNIQUETAG(hMemInfo)        (0)
+#endif
+
+#ifdef PDUMP
+
+#define MAKEUNIQUETAG(hMemInfo)        (((BM_BUF *)(((PVRSRV_KERNEL_MEM_INFO *)(hMemInfo))->sMemBlk.hBuffer))->pMapping)
+
+       IMG_IMPORT PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                                                 IMG_UINT32                    ui32Offset,
+                                                                                 IMG_UINT32                    ui32Value,
+                                                                                 IMG_UINT32                    ui32Mask,
+                                                                                 PDUMP_POLL_OPERATOR   eOperator,
+                                                                                 IMG_UINT32                    ui32Flags,
+                                                                                 IMG_HANDLE                    hUniqueTag);
+
+       IMG_IMPORT PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psProcData,
+                                                                          IMG_PVOID                    pvAltLinAddr,
+                                                                          IMG_PVOID                    pvLinAddr,
+                                                                          PVRSRV_KERNEL_MEM_INFO       *psMemInfo,
+                                                                          IMG_UINT32                   ui32Offset,
+                                                                          IMG_UINT32                   ui32Bytes,
+                                                                          IMG_UINT32                   ui32Flags,
+                                                                          IMG_HANDLE                   hUniqueTag);
+
+       IMG_IMPORT PVRSRV_ERROR PDumpMemKM(IMG_PVOID                    pvAltLinAddr,
+                                                                          PVRSRV_KERNEL_MEM_INFO       *psMemInfo,
+                                                                          IMG_UINT32                   ui32Offset,
+                                                                          IMG_UINT32                   ui32Bytes,
+                                                                          IMG_UINT32                   ui32Flags,
+                                                                          IMG_HANDLE                   hUniqueTag);
+       PVRSRV_ERROR PDumpMemPagesKM(PVRSRV_DEVICE_TYPE eDeviceType,
+                                                                IMG_DEV_PHYADDR                *pPages,
+                                                                IMG_UINT32                     ui32NumPages,
+                                                                IMG_DEV_VIRTADDR       sDevAddr,
+                                                                IMG_UINT32                     ui32Start,
+                                                                IMG_UINT32                     ui32Length,
+                                                                IMG_UINT32                     ui32Flags,
+                                                                IMG_HANDLE                     hUniqueTag);
+
+       PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                                        IMG_HANDLE hOSMemHandle,
+                                                                        IMG_CPU_VIRTADDR pvLinAddr,
+                                                                        IMG_UINT32 ui32Bytes,
+                                                                        IMG_UINT32 ui32Flags,
+                                                                        IMG_BOOL bInitialisePages,
+                                                                        IMG_HANDLE hUniqueTag1,
+                                                                        IMG_HANDLE hUniqueTag2);
+                                                        
+       PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                                        IMG_HANDLE         hOSMemHandle,
+                                                                        IMG_CPU_VIRTADDR       pvLinAddr,
+                                                                        IMG_UINT32                     ui32Bytes,
+                                                                        IMG_UINT32                     ui32Flags,
+                                                                        IMG_BOOL                       bInitialisePages,
+                                                                        IMG_HANDLE                     hUniqueTag1,
+                                                                        IMG_HANDLE                     hUniqueTag2);
+       IMG_VOID PDumpInitCommon(IMG_VOID);
+       IMG_VOID PDumpDeInitCommon(IMG_VOID);
+       IMG_VOID PDumpInit(IMG_VOID);
+       IMG_VOID PDumpDeInit(IMG_VOID);
+       IMG_BOOL PDumpIsSuspended(IMG_VOID);
+       PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID);
+       PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID);
+       IMG_IMPORT PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame);
+       IMG_IMPORT PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
+       IMG_IMPORT PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags);
+
+       PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+                                                                        IMG_UINT32 ui32RegAddr,
+                                                                        IMG_UINT32 ui32RegValue,
+                                                                        IMG_UINT32 ui32Flags);
+       PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+                                                                               IMG_UINT32 ui32RegAddr,
+                                                                               IMG_UINT32 ui32RegValue,
+                                                                               IMG_UINT32 ui32Mask,
+                                                                               IMG_UINT32 ui32Flags);
+       PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName,
+                                                               IMG_UINT32 ui32RegAddr,
+                                                               IMG_UINT32 ui32RegValue,
+                                                               IMG_UINT32 ui32Mask);
+
+       IMG_IMPORT PVRSRV_ERROR PDumpBitmapKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                                 IMG_CHAR *pszFileName,
+                                                                                 IMG_UINT32 ui32FileOffset,
+                                                                                 IMG_UINT32 ui32Width,
+                                                                                 IMG_UINT32 ui32Height,
+                                                                                 IMG_UINT32 ui32StrideInBytes,
+                                                                                 IMG_DEV_VIRTADDR sDevBaseAddr,
+                                                                                 IMG_HANDLE hDevMemContext,
+                                                                                 IMG_UINT32 ui32Size,
+                                                                                 PDUMP_PIXEL_FORMAT ePixelFormat,
+                                                                                 PDUMP_MEM_FORMAT eMemFormat,
+                                                                                 IMG_UINT32 ui32PDumpFlags);
+       IMG_IMPORT PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR *pszPDumpRegName,
+                                                                                  IMG_CHAR *pszFileName,
+                                                                                  IMG_UINT32 ui32FileOffset,
+                                                                                  IMG_UINT32 ui32Address,
+                                                                                  IMG_UINT32 ui32Size,
+                                                                                  IMG_UINT32 ui32PDumpFlags);
+
+       PVRSRV_ERROR PDumpRegKM(IMG_CHAR* pszPDumpRegName,
+                                                       IMG_UINT32 dwReg,
+                                                       IMG_UINT32 dwData);
+
+       PVRSRV_ERROR PDumpComment(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+       PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32   ui32Flags,
+                                                                          IMG_CHAR*    pszFormat,
+                                                                          ...) IMG_FORMAT_PRINTF(2, 3);
+
+       PVRSRV_ERROR PDumpPDReg(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                       IMG_UINT32      ui32Reg,
+                                                       IMG_UINT32      ui32dwData,
+                                                       IMG_HANDLE      hUniqueTag);
+       PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                                        IMG_UINT32             ui32Reg,
+                                                                        IMG_UINT32             ui32Data,
+                                                                        IMG_UINT32             ui32Flags,
+                                                                        IMG_HANDLE             hUniqueTag);
+
+       IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID);
+       IMG_IMPORT IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID);
+
+       IMG_VOID PDumpMallocPagesPhys(PVRSRV_DEVICE_TYPE        eDeviceType,
+                                                                 IMG_UINT32                    ui32DevVAddr,
+                                                                 IMG_PUINT32                   pui32PhysPages,
+                                                                 IMG_UINT32                    ui32NumPages,
+                                                                 IMG_HANDLE                    hUniqueTag);
+       PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+                                                                       IMG_CHAR *pszMemSpace,
+                                                                       IMG_UINT32 *pui32MMUContextID,
+                                                                       IMG_UINT32 ui32MMUType,
+                                                                       IMG_HANDLE hUniqueTag1,
+                                                                       IMG_HANDLE hOSMemHandle,
+                                                                       IMG_VOID *pvPDCPUAddr);
+       PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+                                                                       IMG_CHAR *pszMemSpace,
+                                                                       IMG_UINT32 ui32MMUContextID,
+                                                                       IMG_UINT32 ui32MMUType);
+
+       PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                                  IMG_UINT32 ui32Offset,
+                                                                  IMG_DEV_PHYADDR sPDDevPAddr,
+                                                                  IMG_HANDLE hUniqueTag1,
+                                                                  IMG_HANDLE hUniqueTag2);
+
+       IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame);
+
+       PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                IMG_CHAR                       *pszFileName,
+                                                                IMG_UINT32                     ui32FileOffset,
+                                                                IMG_DEV_VIRTADDR       sDevBaseAddr,
+                                                                IMG_UINT32             ui32Size,
+                                                                IMG_UINT32             ui32DataMaster,
+                                                                IMG_UINT32             ui32PDumpFlags);
+
+       PVRSRV_ERROR PDumpTASignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                  IMG_UINT32   ui32DumpFrameNum,
+                                                                  IMG_UINT32   ui32TAKickCount,
+                                                                  IMG_BOOL             bLastFrame,
+                                                                  IMG_UINT32 *pui32Registers,
+                                                                  IMG_UINT32 ui32NumRegisters);
+
+       PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                                       IMG_UINT32 ui32DumpFrameNum,
+                                                                                       IMG_BOOL bLastFrame,
+                                                                                       IMG_UINT32 *pui32Registers,
+                                                                                       IMG_UINT32 ui32NumRegisters);
+
+       PVRSRV_ERROR PDumpCounterRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                       IMG_UINT32 ui32DumpFrameNum,
+                                       IMG_BOOL                bLastFrame,
+                                       IMG_UINT32 *pui32Registers,
+                                       IMG_UINT32 ui32NumRegisters);
+
+       PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
+                                                               const IMG_UINT32 dwRegOffset,
+                                                               IMG_UINT32      ui32Flags);
+
+       PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                               const IMG_UINT32 dwRegOffset,
+                                                                               IMG_BOOL bLastFrame);
+
+       PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+       PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
+
+       PVRSRV_ERROR PDumpMallocPages(PVRSRV_DEVICE_IDENTIFIER  *psDevID,
+                                                                 IMG_UINT32                            ui32DevVAddr,
+                                                                 IMG_CPU_VIRTADDR                      pvLinAddr,
+                                                                 IMG_HANDLE                            hOSMemHandle,
+                                                                 IMG_UINT32                            ui32NumBytes,
+                                                                 IMG_UINT32                            ui32PageSize,
+                                         IMG_BOOL                                      bShared,
+                                                                 IMG_HANDLE                            hUniqueTag);
+       PVRSRV_ERROR PDumpMallocPageTable(PVRSRV_DEVICE_IDENTIFIER      *psDevId,
+                                                                         IMG_HANDLE            hOSMemHandle,
+                                                                         IMG_UINT32            ui32Offset,
+                                                                         IMG_CPU_VIRTADDR              pvLinAddr,
+                                                                         IMG_UINT32                    ui32NumBytes,
+                                                                         IMG_UINT32                    ui32Flags,
+                                                                         IMG_HANDLE                    hUniqueTag);
+       PVRSRV_ERROR PDumpFreePages(struct _BM_HEAP_    *psBMHeap,
+                                                       IMG_DEV_VIRTADDR        sDevVAddr,
+                                                       IMG_UINT32                      ui32NumBytes,
+                                                       IMG_UINT32                      ui32PageSize,
+                                                       IMG_HANDLE              hUniqueTag,
+                                                       IMG_BOOL                        bInterleaved);
+       PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+                                                                       IMG_HANDLE          hOSMemHandle,
+                                                                       IMG_CPU_VIRTADDR        pvLinAddr,
+                                                                       IMG_UINT32                      ui32NumBytes,
+                                                                       IMG_UINT32                      ui32Flags,
+                                                                       IMG_HANDLE                      hUniqueTag);
+
+       IMG_IMPORT PVRSRV_ERROR PDumpHWPerfCBKM(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                               IMG_CHAR                        *pszFileName,
+                                                                               IMG_UINT32                      ui32FileOffset,
+                                                                               IMG_DEV_VIRTADDR        sDevBaseAddr,
+                                                                               IMG_UINT32                      ui32Size,
+                                                                               IMG_UINT32                      ui32PDumpFlags);
+
+       PVRSRV_ERROR PDumpSignatureBuffer(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+                                                                         IMG_CHAR                      *pszFileName,
+                                                                         IMG_CHAR                      *pszBufferType,
+                                                                         IMG_UINT32            ui32FileOffset,
+                                                                         IMG_DEV_VIRTADDR      sDevBaseAddr,
+                                                                         IMG_UINT32            ui32Size,
+                                                                         IMG_UINT32            ui32PDumpFlags);
+
+       PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO   psROffMemInfo,
+                                 IMG_UINT32                            ui32ROffOffset,
+                                 IMG_UINT32                            ui32WPosVal,
+                                 IMG_UINT32                            ui32PacketSize,
+                                 IMG_UINT32                            ui32BufferSize,
+                                 IMG_UINT32                            ui32Flags,
+                                 IMG_HANDLE                            hUniqueTag);
+
+       PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR          *pszPDumpRegName,
+                                                                 IMG_UINT32    ui32RegOffset,
+                                                                 IMG_UINT32    ui32WPosVal,
+                                                                 IMG_UINT32    ui32PacketSize,
+                                                                 IMG_UINT32    ui32BufferSize,
+                                                                 IMG_UINT32    ui32Flags);
+
+       IMG_VOID PDumpVGXMemToFile(IMG_CHAR *pszFileName,
+                                                          IMG_UINT32 ui32FileOffset, 
+                                                          PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                          IMG_UINT32 uiAddr, 
+                                                          IMG_UINT32 ui32Size,
+                                                          IMG_UINT32 ui32PDumpFlags,
+                                                          IMG_HANDLE hUniqueTag);
+
+       IMG_VOID PDumpSuspendKM(IMG_VOID);
+       IMG_VOID PDumpResumeKM(IMG_VOID);
+
+       
+       PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
+                                                                IMG_CHAR *pszFileName,
+                                                                        IMG_UINT32 ui32FileOffset, 
+                                                                        PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                                                        IMG_UINT32 uiAddr, 
+                                                                        IMG_UINT32 ui32Size,
+                                                                        IMG_UINT32 ui32PDumpFlags,
+                                                                        IMG_HANDLE hUniqueTag);
+
+       #define PDUMPMEMPOL                             PDumpMemPolKM
+       #define PDUMPMEM                                PDumpMemKM
+       #define PDUMPMEMPTENTRIES               PDumpMemPTEntriesKM
+       #define PDUMPPDENTRIES                  PDumpMemPDEntriesKM
+       #define PDUMPMEMUM                              PDumpMemUM
+       #define PDUMPINIT                               PDumpInitCommon
+       #define PDUMPDEINIT                             PDumpDeInitCommon
+       #define PDUMPISLASTFRAME                PDumpIsLastCaptureFrameKM
+       #define PDUMPTESTFRAME                  PDumpIsCaptureFrameKM
+       #define PDUMPTESTNEXTFRAME              PDumpTestNextFrame
+       #define PDUMPREGWITHFLAGS               PDumpRegWithFlagsKM
+       #define PDUMPREG                                PDumpRegKM
+       #define PDUMPCOMMENT                    PDumpComment
+       #define PDUMPCOMMENTWITHFLAGS   PDumpCommentWithFlags
+       #define PDUMPREGPOL                             PDumpRegPolKM
+       #define PDUMPREGPOLWITHFLAGS    PDumpRegPolWithFlagsKM
+       #define PDUMPMALLOCPAGES                PDumpMallocPages
+       #define PDUMPMALLOCPAGETABLE    PDumpMallocPageTable
+       #define PDUMPSETMMUCONTEXT              PDumpSetMMUContext
+       #define PDUMPCLEARMMUCONTEXT    PDumpClearMMUContext
+       #define PDUMPFREEPAGES                  PDumpFreePages
+       #define PDUMPFREEPAGETABLE              PDumpFreePageTable
+       #define PDUMPPDREG                              PDumpPDReg
+       #define PDUMPPDREGWITHFLAGS             PDumpPDRegWithFlags
+       #define PDUMPCBP                                PDumpCBP
+       #define PDUMPREGBASEDCBP                PDumpRegBasedCBP
+       #define PDUMPMALLOCPAGESPHYS    PDumpMallocPagesPhys
+       #define PDUMPENDINITPHASE               PDumpStopInitPhaseKM
+       #define PDUMPBITMAPKM                   PDumpBitmapKM
+       #define PDUMPDRIVERINFO                 PDumpDriverInfoKM
+       #define PDUMPIDLWITHFLAGS               PDumpIDLWithFlags
+       #define PDUMPIDL                                PDumpIDL
+       #define PDUMPSUSPEND                    PDumpSuspendKM
+       #define PDUMPRESUME                             PDumpResumeKM
+
+#else
+               #if ((defined(LINUX) || defined(GCC_IA32)) || defined(GCC_ARM))
+                       #define PDUMPMEMPOL(args...)
+                       #define PDUMPMEM(args...)
+                       #define PDUMPMEMPTENTRIES(args...)
+                       #define PDUMPPDENTRIES(args...)
+                       #define PDUMPMEMUM(args...)
+                       #define PDUMPINIT(args...)
+                       #define PDUMPDEINIT(args...)
+                       #define PDUMPISLASTFRAME(args...)
+                       #define PDUMPTESTFRAME(args...)
+                       #define PDUMPTESTNEXTFRAME(args...)
+                       #define PDUMPREGWITHFLAGS(args...)
+                       #define PDUMPREG(args...)
+                       #define PDUMPCOMMENT(args...)
+                       #define PDUMPREGPOL(args...)
+                       #define PDUMPREGPOLWITHFLAGS(args...)
+                       #define PDUMPMALLOCPAGES(args...)
+                       #define PDUMPMALLOCPAGETABLE(args...)
+                       #define PDUMPSETMMUCONTEXT(args...)
+                       #define PDUMPCLEARMMUCONTEXT(args...)
+                       #define PDUMPFREEPAGES(args...)
+                       #define PDUMPFREEPAGETABLE(args...)
+                       #define PDUMPPDREG(args...)
+                       #define PDUMPPDREGWITHFLAGS(args...)
+                       #define PDUMPSYNC(args...)
+                       #define PDUMPCOPYTOMEM(args...)
+                       #define PDUMPWRITE(args...)
+                       #define PDUMPCBP(args...)
+                       #define PDUMPREGBASEDCBP(args...)
+                       #define PDUMPCOMMENTWITHFLAGS(args...)
+                       #define PDUMPMALLOCPAGESPHYS(args...)
+                       #define PDUMPENDINITPHASE(args...)
+                       #define PDUMPMSVDXREG(args...)
+                       #define PDUMPMSVDXREGWRITE(args...)
+                       #define PDUMPMSVDXREGREAD(args...)
+                       #define PDUMPMSVDXPOLEQ(args...)
+                       #define PDUMPMSVDXPOL(args...)
+                       #define PDUMPBITMAPKM(args...)
+                       #define PDUMPDRIVERINFO(args...)
+                       #define PDUMPIDLWITHFLAGS(args...)
+                       #define PDUMPIDL(args...)
+                       #define PDUMPSUSPEND(args...)
+                       #define PDUMPRESUME(args...)
+                       #define PDUMPMSVDXWRITEREF(args...)
+               #else
+                       #error Compiler not specified
+               #endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/pdump_osfunc.h b/drivers/staging/mrst/pvr/services4/srvkm/include/pdump_osfunc.h
new file mode 100644 (file)
index 0000000..e4c4d00
--- /dev/null
@@ -0,0 +1,139 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <stdarg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define MAX_PDUMP_STRING_LENGTH (256)
+
+
+#define PDUMP_GET_SCRIPT_STRING()                              \
+       IMG_HANDLE hScript;                                                     \
+       IMG_UINT32      ui32MaxLen;                                             \
+       PVRSRV_ERROR eError;                                            \
+       eError = PDumpOSGetScriptString(&hScript, &ui32MaxLen);\
+       if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_MSG_STRING()                                 \
+       IMG_CHAR *pszMsg;                                                       \
+       IMG_UINT32      ui32MaxLen;                                             \
+       PVRSRV_ERROR eError;                                            \
+       eError = PDumpOSGetMessageString(&pszMsg, &ui32MaxLen);\
+       if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_FILE_STRING()                                \
+       IMG_CHAR *pszFileName;                                  \
+       IMG_UINT32      ui32MaxLen;                                     \
+       PVRSRV_ERROR eError;                                    \
+       eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLen);\
+       if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING()             \
+       IMG_HANDLE hScript;                                                     \
+       IMG_CHAR *pszFileName;                                          \
+       IMG_UINT32      ui32MaxLenScript;                               \
+       IMG_UINT32      ui32MaxLenFileName;                             \
+       PVRSRV_ERROR eError;                                            \
+       eError = PDumpOSGetScriptString(&hScript, &ui32MaxLenScript);\
+       if(eError != PVRSRV_OK) return eError;          \
+       eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
+       if(eError != PVRSRV_OK) return eError;
+
+       
+       PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
+
+       
+       PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, IMG_UINT32 *pui32MaxLen);
+
+       
+       PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+
+
+
+
+#define PDUMP_va_list  va_list
+#define PDUMP_va_start va_start
+#define PDUMP_va_end   va_end
+
+
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID);
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSIsSuspended(IMG_VOID);
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID);
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hDbgStream,
+               IMG_UINT8 *psui8Data,
+               IMG_UINT32 ui32Size,
+               IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE        hScript, IMG_UINT32 ui32Flags);
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) IMG_FORMAT_PRINTF(3, 0);
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+        IMG_HANDLE hOSMemHandle,
+               IMG_UINT32 ui32Offset,
+               IMG_UINT8 *pui8LinAddr,
+               IMG_UINT32 ui32PageSize,
+               IMG_DEV_PHYADDR *psDevPAddr);
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+               IMG_UINT32 ui32Offset,
+               IMG_PUINT8 pui8LinAddr,
+               IMG_UINT32 ui32DataPageMask,
+               IMG_UINT32 *pui32PageOffset);
+
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID);
+
+IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID);
+
+PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame);
+
+#if defined (__cplusplus)
+}
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/perproc.h b/drivers/staging/mrst/pvr/services4/srvkm/include/perproc.h
new file mode 100644 (file)
index 0000000..eb9f23c
--- /dev/null
@@ -0,0 +1,128 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __PERPROC_H__
+#define __PERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <linux/sched.h>
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+typedef struct _PVRSRV_PER_PROCESS_DATA_
+{
+       IMG_UINT32              ui32PID;
+       char                    name[TASK_COMM_LEN];
+       IMG_HANDLE              hBlockAlloc;
+       PRESMAN_CONTEXT         hResManContext;
+       IMG_HANDLE              hPerProcData;
+       PVRSRV_HANDLE_BASE      *psHandleBase;
+#if defined (PVR_SECURE_HANDLES)
+       
+       IMG_BOOL                bHandlesBatched;
+#endif  
+       IMG_UINT32              ui32RefCount;
+
+       
+       IMG_BOOL                bInitProcess;
+#if defined(PDUMP)
+       
+       IMG_BOOL                bPDumpPersistent;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+       IMG_BOOL                bPDumpActive;
+#endif
+#endif
+       
+       IMG_HANDLE              hOsPrivateData;
+#if defined(PERPROC_LIST)
+       struct _PVRSRV_PER_PROCESS_DATA_ *psNext;
+       struct _PVRSRV_PER_PROCESS_DATA_ **ppsThis;
+#endif
+} PVRSRV_PER_PROCESS_DATA;
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32    ui32PID, IMG_UINT32 ui32Flags);
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32     ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID);
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID);
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessData)
+#endif
+static INLINE
+PVRSRV_PER_PROCESS_DATA *PVRSRVFindPerProcessData(IMG_VOID)
+{
+       return PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVProcessPrivateData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+       return (psPerProc != IMG_NULL) ? psPerProc->hOsPrivateData : IMG_NULL;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVPerProcessPrivateData(IMG_UINT32 ui32PID)
+{
+       return PVRSRVProcessPrivateData(PVRSRVPerProcessData(ui32PID));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVFindPerProcessPrivateData(IMG_VOID)
+{
+       return PVRSRVProcessPrivateData(PVRSRVFindPerProcessData());
+}
+
+#if defined(PERPROC_LIST)
+PVRSRV_PER_PROCESS_DATA* PVRSRVPerProcessList(IMG_VOID);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/power.h b/drivers/staging/mrst/pvr/services4/srvkm/include/power.h
new file mode 100644 (file)
index 0000000..cd8d737
--- /dev/null
@@ -0,0 +1,133 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef POWER_H
+#define POWER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+typedef struct _PVRSRV_POWER_DEV_TAG_
+{
+       PFN_PRE_POWER                                   pfnPrePower;
+       PFN_POST_POWER                                  pfnPostPower;
+       PFN_PRE_CLOCKSPEED_CHANGE               pfnPreClockSpeedChange;
+       PFN_POST_CLOCKSPEED_CHANGE              pfnPostClockSpeedChange;
+       IMG_HANDLE                                              hDevCookie;
+       IMG_UINT32                                              ui32DeviceIndex;
+       PVRSRV_DEV_POWER_STATE                  eDefaultPowerState;
+       PVRSRV_DEV_POWER_STATE                  eCurrentPowerState;
+       struct _PVRSRV_POWER_DEV_TAG_   *psNext;
+       struct _PVRSRV_POWER_DEV_TAG_   **ppsThis;
+
+} PVRSRV_POWER_DEV;
+
+typedef enum _PVRSRV_INIT_SERVER_STATE_
+{
+       PVRSRV_INIT_SERVER_Unspecified          = -1,   
+       PVRSRV_INIT_SERVER_RUNNING                      = 0,    
+       PVRSRV_INIT_SERVER_RAN                          = 1,    
+       PVRSRV_INIT_SERVER_SUCCESSFUL           = 2,    
+       PVRSRV_INIT_SERVER_NUM                          = 3,    
+       PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_INIT_SERVER_STATE, *PPVRSRV_INIT_SERVER_STATE;
+
+IMG_IMPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE     eInitServerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState);
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32        ui32CallerID,
+                                                        IMG_BOOL       bSystemPowerEvent);
+IMG_IMPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32  ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32                            ui32DeviceIndex,
+                                                                                PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                                                                IMG_UINT32                             ui32CallerID,
+                                                                                IMG_BOOL                               bRetainMutex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM (PVRSRV_SYS_POWER_STATE ePVRState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32                                      ui32DeviceIndex,
+                                                                          PFN_PRE_POWER                                pfnPrePower,
+                                                                          PFN_POST_POWER                               pfnPostPower,
+                                                                          PFN_PRE_CLOCKSPEED_CHANGE    pfnPreClockSpeedChange,
+                                                                          PFN_POST_CLOCKSPEED_CHANGE   pfnPostClockSpeedChange,
+                                                                          IMG_HANDLE                                   hDevCookie,
+                                                                          PVRSRV_DEV_POWER_STATE               eCurrentPowerState,
+                                                                          PVRSRV_DEV_POWER_STATE               eDefaultPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32        ui32DeviceIndex,
+                                                                                        IMG_BOOL       bIdleDevice,
+                                                                                        IMG_VOID       *pvInfo);
+
+IMG_IMPORT
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32   ui32DeviceIndex,
+                                                                                 IMG_BOOL              bIdleDevice,
+                                                                                 IMG_VOID              *pvInfo);
+
+
+/*
+ * PVRSRVPowerOnSystemWithDevice
+ *
+ * Description: Power on the System if it is off, but instead of powering all
+ * of the devices to their "default" state, only turn on the specified
+ * device index.
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerOnSystemWithDevice(IMG_UINT32  ui32DeviceIndex,
+                                          IMG_UINT32   ui32CallerID,
+                                          IMG_BOOL     bRetainMutex);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/queue.h b/drivers/staging/mrst/pvr/services4/srvkm/include/queue.h
new file mode 100644 (file)
index 0000000..9437f09
--- /dev/null
@@ -0,0 +1,111 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define UPDATE_QUEUE_ROFF(psQueue, ui32Size)                                           \
+       (psQueue)->ui32ReadOffset = ((psQueue)->ui32ReadOffset + (ui32Size))    \
+       & ((psQueue)->ui32QueueSize - 1);
+
+ typedef struct _COMMAND_COMPLETE_DATA_
+ {
+       IMG_BOOL                        bInUse;
+               
+       IMG_UINT32                      ui32DstSyncCount;       
+       IMG_UINT32                      ui32SrcSyncCount;       
+       PVRSRV_SYNC_OBJECT      *psDstSync;                     
+       PVRSRV_SYNC_OBJECT      *psSrcSync;                     
+       IMG_UINT32                      ui32AllocSize;          
+ }COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
+
+#if !defined(USE_CODE)
+IMG_VOID QueueDumpDebugInfo(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVProcessQueues (IMG_UINT32   ui32CallerID,
+                                                                 IMG_BOOL              bFlush);
+
+#if defined(__linux__) && defined(__KERNEL__) 
+#include <linux/types.h>
+#include <linux/seq_file.h>
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off);
+void ProcSeqShowQueue(struct seq_file *sfile,void* el);
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+                                                                                                        PVRSRV_QUEUE_INFO **ppsQueueInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO      *psQueue,
+                                                                                               PVRSRV_COMMAND          **ppsCommand,
+                                                                                               IMG_UINT32                      ui32DevIndex,
+                                                                                               IMG_UINT16                      CommandType,
+                                                                                               IMG_UINT32                      ui32DstSyncCount,
+                                                                                               PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+                                                                                               IMG_UINT32                      ui32SrcSyncCount,
+                                                                                               PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+                                                                                               IMG_SIZE_T                      ui32DataByteSize );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+                                                                                               IMG_SIZE_T ui32ParamSize,
+                                                                                               IMG_VOID **ppvSpace);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+                                                                                               PVRSRV_COMMAND *psCommand);
+
+IMG_IMPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, IMG_BOOL bScheduleMISR);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32            ui32DevIndex,
+                                                                                PFN_CMD_PROC   *ppfnCmdProcList,
+                                                                                IMG_UINT32             ui32MaxSyncsPerCmd[][2],
+                                                                                IMG_UINT32             ui32CmdCount);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32      ui32DevIndex,
+                                                                          IMG_UINT32   ui32CmdCount);
+
+#endif 
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/ra.h b/drivers/staging/mrst/pvr/services4/srvkm/include/ra.h
new file mode 100644 (file)
index 0000000..f28ce4c
--- /dev/null
@@ -0,0 +1,159 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _RA_H_
+#define _RA_H_
+
+#include "img_types.h"
+#include "hash.h"
+#include "osfunc.h"
+
+typedef struct _RA_ARENA_ RA_ARENA;                    
+typedef struct _BM_MAPPING_ BM_MAPPING;
+
+
+
+#define RA_STATS 
+
+
+struct _RA_STATISTICS_
+{
+    
+    IMG_SIZE_T uSpanCount;
+
+    
+    IMG_SIZE_T uLiveSegmentCount;
+
+    
+    IMG_SIZE_T uFreeSegmentCount;
+
+    
+    IMG_SIZE_T uTotalResourceCount;
+    
+    
+    IMG_SIZE_T uFreeResourceCount;
+
+    
+    IMG_SIZE_T uCumulativeAllocs;
+
+    
+    IMG_SIZE_T uCumulativeFrees;
+
+    
+    IMG_SIZE_T uImportCount;
+
+    
+    IMG_SIZE_T uExportCount;
+};
+typedef struct _RA_STATISTICS_ RA_STATISTICS;
+
+struct _RA_SEGMENT_DETAILS_
+{
+       IMG_SIZE_T      uiSize;
+       IMG_CPU_PHYADDR sCpuPhyAddr;
+       IMG_HANDLE      hSegment;
+};
+typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+           IMG_UINTPTR_T base,
+           IMG_SIZE_T uSize,
+           BM_MAPPING *psMapping,
+           IMG_SIZE_T uQuantum, 
+           IMG_BOOL (*imp_alloc)(IMG_VOID *_h,
+                                IMG_SIZE_T uSize,
+                                IMG_SIZE_T *pActualSize,
+                                BM_MAPPING **ppsMapping,
+                                IMG_UINT32 uFlags,
+                                IMG_UINTPTR_T *pBase),
+           IMG_VOID (*imp_free) (IMG_VOID *,
+                                IMG_UINTPTR_T,
+                                BM_MAPPING *),
+           IMG_VOID (*backingstore_free) (IMG_VOID *,
+                                          IMG_SIZE_T,
+                                          IMG_SIZE_T,
+                                          IMG_HANDLE),
+           IMG_VOID *import_handle);
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize);
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena, 
+          IMG_SIZE_T uSize,
+          IMG_SIZE_T *pActualSize,
+          BM_MAPPING **ppsMapping, 
+          IMG_UINT32 uFlags,
+          IMG_UINT32 uAlignment,
+                 IMG_UINT32 uAlignmentOffset,
+          IMG_UINTPTR_T *pBase);
+
+IMG_VOID 
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
+
+
+#ifdef RA_STATS
+
+#define CHECK_SPACE(total)                                     \
+{                                                                                      \
+       if((total)<100)                                                         \
+               return PVRSRV_ERROR_INVALID_PARAMS;     \
+}
+
+#define UPDATE_SPACE(str, count, total)                \
+{                                                                                      \
+       if((count) == -1)                                                       \
+               return PVRSRV_ERROR_INVALID_PARAMS;     \
+       else                                                                    \
+       {                                                                               \
+               (str) += (count);                                               \
+               (total) -= (count);                                             \
+       }                                                                               \
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails);
+
+
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+                                                       IMG_CHAR **ppszStr, 
+                                                       IMG_UINT32 *pui32StrLen);
+
+PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
+                                                               IMG_CHAR **ppszStr, 
+                                                               IMG_UINT32 *pui32StrLen);
+
+#endif 
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/resman.h b/drivers/staging/mrst/pvr/services4/srvkm/include/resman.h
new file mode 100644 (file)
index 0000000..6e6401b
--- /dev/null
@@ -0,0 +1,128 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef __RESMAN_H__
+#define __RESMAN_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#ifdef RES_MAN_EXTEND
+#include <stdarg.h>
+#endif
+#include "servicesext.h"
+
+enum {
+       
+       RESMAN_TYPE_SHARED_PB_DESC = 1,                                 
+       RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,                         
+       RESMAN_TYPE_HW_RENDER_CONTEXT,                                  
+       RESMAN_TYPE_HW_TRANSFER_CONTEXT,                                
+       RESMAN_TYPE_HW_2D_CONTEXT,                                              
+       RESMAN_TYPE_TRANSFER_CONTEXT,                                   
+
+       
+       
+       
+       
+       RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,                 
+       RESMAN_TYPE_DISPLAYCLASS_DEVICE,                                
+
+       
+       RESMAN_TYPE_BUFFERCLASS_DEVICE,                                 
+       
+       
+       RESMAN_TYPE_OS_USERMODE_MAPPING,                                
+       
+       
+       RESMAN_TYPE_DEVICEMEM_CONTEXT,                                  
+       RESMAN_TYPE_DEVICECLASSMEM_MAPPING,                             
+       RESMAN_TYPE_DEVICEMEM_MAPPING,                                  
+       RESMAN_TYPE_DEVICEMEM_WRAP,                                             
+       RESMAN_TYPE_DEVICEMEM_ALLOCATION,                               
+       RESMAN_TYPE_EVENT_OBJECT,                                               
+    RESMAN_TYPE_SHARED_MEM_INFO,                    
+    RESMAN_TYPE_MODIFY_SYNC_OPS,                                       
+    RESMAN_TYPE_SYNC_INFO,                                             
+       
+       
+       RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION                 
+};
+
+#define RESMAN_CRITERIA_ALL                            0x00000000      
+#define RESMAN_CRITERIA_RESTYPE                        0x00000001      
+#define RESMAN_CRITERIA_PVOID_PARAM            0x00000002      
+#define RESMAN_CRITERIA_UI32_PARAM             0x00000004      
+
+typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam, IMG_UINT32 ui32Param); 
+
+typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
+typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+
+PVRSRV_ERROR ResManInit(IMG_VOID);
+IMG_VOID ResManDeInit(IMG_VOID);
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT hResManContext,
+                                                          IMG_UINT32           ui32ResType, 
+                                                          IMG_PVOID            pvParam, 
+                                                          IMG_UINT32           ui32Param, 
+                                                          RESMAN_FREE_FN       pfnFreeResource);
+
+PVRSRV_ERROR ResManFreeResByPtr(PRESMAN_ITEM   psResItem);
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT   hResManContext,
+                                                                        IMG_UINT32                     ui32SearchCriteria, 
+                                                                        IMG_UINT32                     ui32ResType, 
+                                                                        IMG_PVOID                      pvParam, 
+                                                                        IMG_UINT32                     ui32Param);
+
+PVRSRV_ERROR ResManDissociateRes(PRESMAN_ITEM          psResItem,
+                                                        PRESMAN_CONTEXT        psNewResManContext);
+
+PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT   hResManContext,
+                                                                        PRESMAN_ITEM           psItem);
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE                    hPerProc,
+                                                                PRESMAN_CONTEXT        *phResManContext);
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT hResManContext,
+                                                               IMG_BOOL                bKernelContext);
+#ifdef RES_MAN_EXTEND
+PVRSRV_ERROR PVRSRVResManAnyByCriteria(PRESMAN_CONTEXT psResManContext,
+                                       IMG_UINT32 ui32SearchCriteria,
+                                       IMG_UINT32              ui32ResType,
+                                       IMG_PVOID               pvParam,
+                                       IMG_UINT32              ui32Param,
+                                       PVRSRV_ERROR(*pfnCallBack)(PRESMAN_ITEM psRes, va_list va), ...);
+IMG_PVOID PVRSRVGetResData(PRESMAN_ITEM psResItem);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/services_headers.h b/drivers/staging/mrst/pvr/services4/srvkm/include/services_headers.h
new file mode 100644 (file)
index 0000000..f5f3db2
--- /dev/null
@@ -0,0 +1,50 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef SERVICES_HEADERS_H
+#define SERVICES_HEADERS_H
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG          1
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "power.h"
+#include "resman.h"
+#include "queue.h"
+#include "srvkm.h"
+#include "kerneldisplay.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "metrics.h"
+#include "osfunc.h"
+#include "ossync.h"
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/srvkm/include/srvkm.h b/drivers/staging/mrst/pvr/services4/srvkm/include/srvkm.h
new file mode 100644 (file)
index 0000000..e8e223c
--- /dev/null
@@ -0,0 +1,78 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef SRVKM_H
+#define SRVKM_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+       
+       #ifdef PVR_DISABLE_LOGGING
+       #define PVR_LOG(X)
+       #else
+        
+       #define PVR_LOG(X)                      PVRSRVReleasePrintf X;
+       #endif
+
+       IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+       IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32    ui32PID, IMG_UINT32 ui32Flags);
+       IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32     ui32PID);
+
+       IMG_IMPORT IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID);
+
+       IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
+
+       PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, IMG_SIZE_T *puiBufSize, IMG_BOOL bSave);
+
+       IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
+{\
+       IMG_UINT32 uiOffset, uiStart, uiCurrent; \
+       IMG_INT32 iNotLastLoop;                                  \
+       for(uiOffset = 0, uiStart = OSClockus(), uiCurrent = uiStart + 1, iNotLastLoop = 1;\
+               ((uiCurrent - uiStart + uiOffset) < (TIMEOUT)) || iNotLastLoop--;                               \
+               uiCurrent = OSClockus(),                                                                                                        \
+               uiOffset = uiCurrent < uiStart ? IMG_UINT32_MAX - uiStart : uiOffset,           \
+               uiStart = uiCurrent < uiStart ? 0 : uiStart)
+
+#define END_LOOP_UNTIL_TIMEOUT() \
+}
+
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/system/include/syscommon.h b/drivers/staging/mrst/pvr/services4/system/include/syscommon.h
new file mode 100644 (file)
index 0000000..34855da
--- /dev/null
@@ -0,0 +1,220 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _SYSCOMMON_H
+#define _SYSCOMMON_H
+
+#include "sysconfig.h"      
+#include "sysinfo.h"           
+#include "servicesint.h"
+#include "queue.h"
+#include "power.h"
+#include "resman.h"
+#include "ra.h"
+#include "device.h"
+#include "buffer_manager.h"
+#include "pvr_debug.h"
+#include "services.h"
+
+#if defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__)
+#include <asm/io.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct _SYS_DEVICE_ID_TAG
+{
+       IMG_UINT32      uiID;
+       IMG_BOOL        bInUse;
+
+} SYS_DEVICE_ID;
+
+
+#define SYS_MAX_LOCAL_DEVMEM_ARENAS    4
+
+typedef struct _SYS_DATA_TAG_
+{
+    IMG_UINT32                  ui32NumDevices;                
+       SYS_DEVICE_ID                           sDeviceID[SYS_DEVICE_COUNT];
+    PVRSRV_DEVICE_NODE                 *psDeviceNodeList;                      
+    PVRSRV_POWER_DEV                   *psPowerDeviceList;                     
+       PVRSRV_RESOURCE                         sPowerStateChangeResource;      
+       PVRSRV_SYS_POWER_STATE          eCurrentPowerState;                     
+       PVRSRV_SYS_POWER_STATE          eFailedPowerState;                      
+       IMG_UINT32                                      ui32CurrentOSPowerState;        
+    PVRSRV_QUEUE_INFO           *psQueueList;                  
+       PVRSRV_KERNEL_SYNC_INFO         *psSharedSyncInfoList;          
+    IMG_PVOID                   pvEnvSpecificData;             
+    IMG_PVOID                   pvSysSpecificData;             
+       PVRSRV_RESOURCE                         sQProcessResource;                      
+       IMG_VOID                                        *pvSOCRegsBase;                         
+    IMG_HANDLE                  hSOCTimerRegisterOSMemHandle; 
+       IMG_UINT32                                      *pvSOCTimerRegisterKM;          
+       IMG_VOID                                        *pvSOCClockGateRegsBase;        
+       IMG_UINT32                                      ui32SOCClockGateRegsSize;
+
+       struct _DEVICE_COMMAND_DATA_ *apsDeviceCommandData[SYS_DEVICE_COUNT];
+                                                                                                                       
+
+       IMG_BOOL                    bReProcessQueues;                   
+
+       RA_ARENA                                        *apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS]; 
+
+    IMG_CHAR                    *pszVersionString;          
+       PVRSRV_EVENTOBJECT                      *psGlobalEventObject;                   
+
+       PVRSRV_MISC_INFO_CPUCACHEOP_TYPE ePendingCacheOpType;   
+} SYS_DATA;
+
+
+
+PVRSRV_ERROR SysInitialise(IMG_VOID);
+PVRSRV_ERROR SysFinalise(IMG_VOID);
+
+PVRSRV_ERROR SysDeinitialise(SYS_DATA *psSysData);
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+                                                                       IMG_VOID **ppvDeviceMap);
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA                      *psSysData,
+                                                                PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits);
+
+PVRSRV_ERROR SysResetDevice(IMG_UINT32 ui32DeviceIndex);
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+                                                                       PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                                                       PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+                                                                        PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                                                        PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR SysPowerLockWrap(SYS_DATA *psSysData);
+IMG_VOID SysPowerLockUnwrap(SYS_DATA *psSysData);
+#endif
+
+PVRSRV_ERROR SysOEMFunction (  IMG_UINT32      ui32ID,
+                                                               IMG_VOID        *pvIn,
+                                                               IMG_UINT32  ulInSize,
+                                                               IMG_VOID        *pvOut,
+                                                               IMG_UINT32      ulOutSize);
+
+
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR cpu_paddr);
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR SysPAddr);
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr);
+#if defined(PVR_LMA)
+IMG_BOOL SysVerifyCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR CpuPAddr);
+IMG_BOOL SysVerifySysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+#endif
+
+extern SYS_DATA* gpsSysData;
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireData)
+#endif
+static INLINE IMG_VOID SysAcquireData(SYS_DATA **ppsSysData)
+{
+       
+       *ppsSysData = gpsSysData;
+
+       
+
+
+
+       PVR_ASSERT (gpsSysData != IMG_NULL);
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireDataNoCheck)
+#endif
+static INLINE SYS_DATA * SysAcquireDataNoCheck(IMG_VOID)
+{
+       
+       return gpsSysData;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysInitialiseCommon)
+#endif
+static INLINE PVRSRV_ERROR SysInitialiseCommon(SYS_DATA *psSysData)
+{
+       PVRSRV_ERROR    eError;
+
+       
+       eError = PVRSRVInit(psSysData);
+
+       return eError;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDeinitialiseCommon)
+#endif
+static INLINE IMG_VOID SysDeinitialiseCommon(SYS_DATA *psSysData)
+{
+       
+       PVRSRVDeInit(psSysData);
+
+       OSDestroyResource(&psSysData->sPowerStateChangeResource);
+}
+#endif 
+
+
+#if !(defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__))
+#define        SysReadHWReg(p, o) OSReadHWReg(p, o)
+#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
+#else  
+static inline IMG_UINT32 SysReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+       return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
+}
+
+static inline IMG_VOID SysWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+       writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+}
+#endif 
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/extsyscache.h b/drivers/staging/mrst/pvr/services4/system/unified/extsyscache.h
new file mode 100644 (file)
index 0000000..c3b9517
--- /dev/null
@@ -0,0 +1,44 @@
+#include "sgxdefs.h"
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+/*
+       byte offsets to ext cache control registers from the
+       base of the external register bank
+       - TO BE SPECIFIED IN SYSTEM PORT!
+*/
+/* global invalidate */
+/* This address must be the physical address of the cache controller rounded
+   down to the nearest page*/
+#define SYS_EXT_SYS_CACHE_GBL_INV_REG_OFFSET   0x80000000
+
+
+/* per address invalidate (data written in the address) */
+/* This is the offset within the page to the cache controller which we want
+   to write */
+#define SYS_EXT_SYS_CACHE_ADDR_INV_REG_OFFSET  0x0
+
+/*
+       FIXME: these two defines should really live in sgxconfig.h as a heap define
+       not possible right now due to .h include issues
+*/
+
+/* This address must not live within the same virtal address as
+   any of the heaps, but must be within a shared heap */
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
+#define SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE                        (0xF8FFE000)
+#endif
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+#define SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE                        (0x0F3FE000)
+#endif
+
+/* assume 4k is enough range to cover all control registers */
+#define SGX_EXT_SYSTEM_CACHE_REGS_SIZE                                  0x00001000
+
+#define INVALIDATE_EXT_SYSTEM_CACHE_INLINE(RegA)                                                                       \
+       mov             RegA, HSH(SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE);                                             \
+       stad.bpcache    [RegA, HSH(SYS_EXT_SYS_CACHE_ADDR_INV_REG_OFFSET>>2)], HSH(0);  \
+       idf             drc0, st;                                                                                                                               \
+       wdf             drc0;
+#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/oemfuncs.h b/drivers/staging/mrst/pvr/services4/system/unified/oemfuncs.h
new file mode 100644 (file)
index 0000000..0d3b6d7
--- /dev/null
@@ -0,0 +1,72 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__OEMFUNCS_H__)
+#define __OEMFUNCS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define OEM_EXCHANGE_POWER_STATE       (1<<0)
+#define OEM_DEVICE_MEMORY_POWER                (1<<1)
+#define OEM_DISPLAY_POWER                      (1<<2)
+#define OEM_GET_EXT_FUNCS                      (1<<3)
+
+typedef struct OEM_ACCESS_INFO_TAG
+{
+       IMG_UINT32              ui32Size;
+       IMG_UINT32      ui32FBPhysBaseAddress;
+       IMG_UINT32              ui32FBMemAvailable;             
+       IMG_UINT32      ui32SysPhysBaseAddress;
+       IMG_UINT32              ui32SysSize;
+       IMG_UINT32              ui32DevIRQ;
+} OEM_ACCESS_INFO, *POEM_ACCESS_INFO; 
+typedef IMG_UINT32   (*PFN_SRV_BRIDGEDISPATCH)( IMG_UINT32  Ioctl,
+                                                                                               IMG_BYTE   *pInBuf,
+                                                                                               IMG_UINT32  InBufLen, 
+                                                                                           IMG_BYTE   *pOutBuf,
+                                                                                               IMG_UINT32  OutBufLen,
+                                                                                               IMG_UINT32 *pdwBytesTransferred);
+
+
+typedef PVRSRV_ERROR (*PFN_SRV_READREGSTRING)(PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+typedef struct PVRSRV_DC_OEM_JTABLE_TAG
+{
+       PFN_SRV_BRIDGEDISPATCH                  pfnOEMBridgeDispatch;
+       PFN_SRV_READREGSTRING                   pfnOEMReadRegistryString;
+       PFN_SRV_READREGSTRING                   pfnOEMWriteRegistryString;
+
+} PVRSRV_DC_OEM_JTABLE;
+#if defined(__cplusplus)
+}
+#endif
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_export.c b/drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_export.c
new file mode 100644 (file)
index 0000000..2ad4fee
--- /dev/null
@@ -0,0 +1,202 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "pvr_drm_shared.h"
+
+#include "services_headers.h"
+#include "private_data.h"
+#include "pvr_drm.h"
+
+#include "pvr_bridge.h"
+#include "mutex.h"
+#include "lock.h"
+#include "linkage.h"
+#include "mmap.h"
+
+#if defined(PDUMP)
+#include "client/linuxsrv.h"
+#endif
+
+#include "sys_pvr_drm_import.h"
+
+#include "sys_pvr_drm_export.h"
+
+int
+SYSPVRInit(void)
+{
+       PVRDPFInit();
+
+       return 0;
+}
+
+int
+SYSPVRLoad(struct drm_device *dev, unsigned long flags)
+{
+       return PVRSRVDrmLoad(dev, flags);
+}
+
+int
+SYSPVROpen(struct drm_device *dev, struct drm_file *pFile)
+{
+       return PVRSRVDrmOpen(dev, pFile);
+}
+
+int
+SYSPVRUnload(struct drm_device *dev)
+{
+       return PVRSRVDrmUnload(dev);
+}
+
+void
+SYSPVRPostClose(struct drm_device *dev, struct drm_file *file)
+{
+       return PVRSRVDrmPostClose(dev, file);
+}
+
+int
+SYSPVRBridgeDispatch(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+       return PVRSRV_BridgeDispatchKM(dev, arg, pFile);
+}
+
+int
+SYSPVRDCDriverIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+       return PVRDRM_Dummy_ioctl(dev, arg, pFile);
+
+}
+
+int
+SYSPVRBCDriverIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+       return PVRDRM_Dummy_ioctl(dev, arg, pFile);
+
+}
+
+int
+SYSPVRIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+       return PVRDRMIsMaster(dev, arg, pFile);
+}
+
+int
+SYSPVRUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+       return PVRDRMUnprivCmd(dev, arg, pFile);
+}
+
+int
+SYSPVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+       int ret;
+
+       ret = PVRMMap(pFile, ps_vma);
+       if (ret == -ENOENT)
+       {
+               ret = drm_mmap(pFile, ps_vma);
+       }
+
+       return ret;
+}
+
+int
+SYSPVRDBGDrivIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+#if defined(PDUMP)
+       return dbgdrv_ioctl(dev, arg, pFile);
+#else
+       PVR_UNREFERENCED_PARAMETER(dev);
+       PVR_UNREFERENCED_PARAMETER(arg);
+       PVR_UNREFERENCED_PARAMETER(pFile);
+
+       return -EINVAL;
+#endif
+}
+
+void
+SYSPVRSuspendLock(struct drm_device *dev)
+{
+       PVR_UNREFERENCED_PARAMETER(dev);
+
+       LinuxLockMutex(&gPVRSRVLock);
+}
+
+void
+SYSPVRSuspendUnlock(struct drm_device *dev)
+{
+       PVR_UNREFERENCED_PARAMETER(dev);
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+int
+SYSPVRPreSuspend(struct drm_device *dev)
+{
+       if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+       {
+               return -EBUSY;
+       }
+
+#if defined(DISPLAY_CONTROLLER)
+        if (PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Suspend)(dev) != 0)
+        {
+               (void)PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0);
+                return -EBUSY;
+        }
+#else
+       PVR_UNREFERENCED_PARAMETER(dev);
+#endif
+
+       return 0;
+}
+
+int
+SYSPVRPostSuspend(struct drm_device *dev)
+{
+       if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+       {
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+int
+SYSPVRResume(struct drm_device *dev)
+{
+#if defined(DISPLAY_CONTROLLER)
+        if (PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Resume)(dev) != 0)
+        {
+                return -EINVAL;
+        }
+#else
+       PVR_UNREFERENCED_PARAMETER(dev);
+#endif
+       return 0;
+}
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_export.h b/drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_export.h
new file mode 100644 (file)
index 0000000..3a87972
--- /dev/null
@@ -0,0 +1,97 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__SYS_PVR_DRM_EXPORT_H__)
+#define __SYS_PVR_DRM_EXPORT_H__
+
+#include "pvr_drm_shared.h"
+
+#if defined(__KERNEL__)
+
+#include "services_headers.h"
+#include "private_data.h"
+#include "pvr_drm.h"
+
+#include "pvr_bridge.h"
+
+#if defined(PDUMP)
+#include "client/linuxsrv.h"
+#endif
+
+#define PVR_DRM_SRVKM_IOCTL \
+       DRM_IOW(DRM_COMMAND_BASE + PVR_DRM_SRVKM_CMD, PVRSRV_BRIDGE_PACKAGE)
+
+#define PVR_DRM_DISP_IOCTL \
+       DRM_IO(DRM_COMMAND_BASE + PVR_DRM_DISP_CMD)
+
+#define PVR_DRM_BC_IOCTL \
+       DRM_IO(DRM_COMMAND_BASE + PVR_DRM_BC_CMD)
+
+#define        PVR_DRM_IS_MASTER_IOCTL \
+       DRM_IO(DRM_COMMAND_BASE + PVR_DRM_IS_MASTER_CMD)
+
+#define        PVR_DRM_UNPRIV_IOCTL \
+       DRM_IOWR(DRM_COMMAND_BASE + PVR_DRM_UNPRIV_CMD, IMG_UINT32)
+
+#if defined(PDUMP)
+#define        PVR_DRM_DBGDRV_IOCTL \
+       DRM_IOW(DRM_COMMAND_BASE + PVR_DRM_DBGDRV_CMD, IOCTL_PACKAGE)
+#else
+#define        PVR_DRM_DBGDRV_IOCTL \
+       DRM_IO(DRM_COMMAND_BASE + PVR_DRM_DBGDRV_CMD)
+#endif
+
+int SYSPVRInit(void);
+int SYSPVRLoad(struct drm_device *dev, unsigned long flags);
+int SYSPVROpen(struct drm_device *dev, struct drm_file *pFile);
+int SYSPVRUnload(struct drm_device *dev);
+void SYSPVRPostClose(struct drm_device *dev, struct drm_file *file);
+int SYSPVRBridgeDispatch(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int SYSPVRDCDriverIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int SYSPVRBCDriverIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int SYSPVRIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int SYSPVRUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+int SYSPVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+int SYSPVRDBGDrivIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+int SYSPVRServiceSGXInterrupt(struct drm_device *dev);
+
+void SYSPVRSuspendLock(struct drm_device *dev);
+void SYSPVRSuspendUnlock(struct drm_device *dev);
+int SYSPVRPreSuspend(struct drm_device *dev);
+int SYSPVRPostSuspend(struct drm_device *dev);
+int SYSPVRResume(struct drm_device *dev);
+
+int BC_Video_ModInit(void);
+int BC_Video_ModCleanup(void);
+int BC_Video_Bridge(struct drm_device *dev, IMG_VOID *arg, struct drm_file *file_priv);
+
+#endif 
+
+#endif 
+
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_import.h b/drivers/staging/mrst/pvr/services4/system/unified/sys_pvr_drm_import.h
new file mode 100644 (file)
index 0000000..635d903
--- /dev/null
@@ -0,0 +1,46 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__SYS_PVR_DRM_IMPORT_H__)
+#define __SYS_PVR_DRM_IMPORT_H__
+
+#if defined(__KERNEL__)
+#include "psb_drm.h"
+#endif
+
+#define DRM_PSB_PLACEMENT_OFFSET   0x13
+
+#if 0
+#define DRM_PVR_RESERVED1      0x0D
+#define DRM_PVR_RESERVED2      0x0E
+#define DRM_PVR_RESERVED3      0x0F
+#define DRM_PVR_RESERVED4      0x10
+#define DRM_PVR_RESERVED5      0x11
+#define DRM_PVR_RESERVED6      0x12
+#endif
+
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/sysconfig.c b/drivers/staging/mrst/pvr/services4/system/unified/sysconfig.c
new file mode 100644 (file)
index 0000000..d340132
--- /dev/null
@@ -0,0 +1,1307 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM)
+#include "linux/pci.h"
+#endif
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "kerneldisplay.h"
+#include "oemfuncs.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pdump_km.h"
+#include "syslocal.h"
+#include "mdfld_gl3.h"
+#if defined(SUPPORT_DRI_DRM_EXT)
+#include "env_data.h"
+#include "psb_drv.h"
+#include "psb_powermgmt.h"
+#include "sys_pvr_drm_export.h"
+#include "msvdx_power.h"
+#include "topaz_power.h"
+#endif
+
+
+/* Graphics MSI address and data region in PCIx */
+#define MRST_PCIx_MSI_ADDR_LOC         0x94
+#define MRST_PCIx_MSI_DATA_LOC         0x98
+
+#define SYS_SGX_CLOCK_SPEED                    (400000000)
+#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ                (100)
+#define SYS_SGX_PDS_TIMER_FREQ                 (1000)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS                (5)
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define        DRI_DRM_STATIC
+#else
+#define        DRI_DRM_STATIC  static
+#endif
+SYS_DATA* gpsSysData = (SYS_DATA*)IMG_NULL;
+SYS_DATA  gsSysData;
+
+static SYS_SPECIFIC_DATA gsSysSpecificData;
+
+IMG_UINT32 gui32SGXDeviceID;
+extern IMG_UINT32      gui32MRSTDisplayDeviceID;
+IMG_UINT32             gui32MRSTMSVDXDeviceID;
+IMG_UINT32             gui32MRSTTOPAZDeviceID;
+
+static SGX_DEVICE_MAP  gsSGXDeviceMap;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+static PVRSRV_DEVICE_NODE *gpsSGXDevNode;
+#endif
+
+#if !defined(NO_HARDWARE)
+IMG_CPU_VIRTADDR gsPoulsboRegsCPUVaddr;
+
+IMG_CPU_VIRTADDR gsPoulsboDisplayRegsCPUVaddr;
+#endif
+
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM)
+extern struct pci_dev *gpsPVRLDMDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+IMG_UINT32 PVRSRV_BridgeDispatchKM( IMG_UINT32  Ioctl,
+                                                                       IMG_BYTE   *pInBuf,
+                                                                       IMG_UINT32  InBufLen,
+                                                                       IMG_BYTE   *pOutBuf,
+                                                                       IMG_UINT32  OutBufLen,
+                                                                       IMG_UINT32 *pdwBytesTransferred);
+#endif
+
+#define        POULSBO_ADDR_RANGE_INDEX        (MMADR_INDEX - 4)
+#define        POULSBO_HP_ADDR_RANGE_INDEX     (GMADR_INDEX - 4)
+static PVRSRV_ERROR PCIInitDev(SYS_DATA *psSysData)
+{
+       SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+       IMG_UINT32 ui32MaxOffset = POULSBO_MAX_OFFSET;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+       psSysSpecData->hSGXPCI = OSPCISetDev((IMG_VOID *)psSysSpecData->psPCIDev, 0);
+       ui32MaxOffset = POULSBO_MAX_OFFSET;
+
+#else
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM)
+       psSysSpecData->hSGXPCI = OSPCISetDev((IMG_VOID *)psSysSpecData->psPCIDev, HOST_PCI_INIT_FLAG_BUS_MASTER | HOST_PCI_INIT_FLAG_MSI);
+#else
+       psSysSpecData->hSGXPCI = OSPCIAcquireDev(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, HOST_PCI_INIT_FLAG_BUS_MASTER | HOST_PCI_INIT_FLAG_MSI);
+#endif
+#endif
+       if (!psSysSpecData->hSGXPCI)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Failed to acquire PCI device"));
+               return PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND;
+       }
+
+        SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV);
+
+       PVR_TRACE(("PCI memory region: %x to %x", OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX), OSPCIAddrRangeEnd(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX)));
+#if defined(SGX_FEATURE_HOST_PORT)
+       PVR_TRACE(("Host Port region: %x to %x", OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX), OSPCIAddrRangeEnd(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX)));
+#endif
+
+       if (OSPCIAddrRangeLen(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX) < ui32MaxOffset)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region isn't big enough"));
+               return PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+       }
+
+
+       if (OSPCIRequestAddrRange(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region not available"));
+               return PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
+
+       }
+        SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE);
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+       if (OSPCIRequestAddrRange(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Host Port region not available"));
+               return PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
+       }
+        SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE);
+#endif
+       return PVRSRV_OK;
+}
+
+static IMG_VOID PCIDeInitDev(SYS_DATA *psSysData)
+{
+       SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+       if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE))
+       {
+               OSPCIReleaseAddrRange(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX);
+       }
+#if defined(SGX_FEATURE_HOST_PORT)
+       if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE))
+       {
+               OSPCIReleaseAddrRange(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX);
+       }
+#endif
+       if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV))
+       {
+               OSPCIReleaseDev(psSysSpecData->hSGXPCI);
+       }
+}
+static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData)
+{
+       IMG_UINT32 ui32BaseAddr = 0;
+       IMG_UINT32 ui32IRQ = 0;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+       IMG_UINT32 ui32HostPortAddr = 0;
+#endif
+       SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+   struct drm_psb_private *dev_priv = (struct drm_psb_private *) gpDrmDevice->dev_private;
+#endif
+
+       ui32BaseAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX);
+#if defined(SGX_FEATURE_HOST_PORT)
+       ui32HostPortAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX);
+#endif
+       if (OSPCIIRQ(psSysSpecData->hSGXPCI, &ui32IRQ) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Couldn't get IRQ"));
+               return PVRSRV_ERROR_INVALID_DEVICE;
+       }
+
+       PVR_TRACE(("ui32BaseAddr: %08X", ui32BaseAddr));
+#if defined(SGX_FEATURE_HOST_PORT)
+       PVR_TRACE(("ui32HostPortAddr: %08X", ui32HostPortAddr));
+#endif
+       PVR_TRACE(("IRQ: %d", ui32IRQ));
+
+
+       gsSGXDeviceMap.ui32Flags = 0x0;
+       gsSGXDeviceMap.ui32IRQ = ui32IRQ;
+
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+       gsSGXDeviceMap.sRegsSysPBase.uiAddr = ui32BaseAddr + SGX_REGS_OFFSET;
+#else
+       gsSGXDeviceMap.sRegsSysPBase.uiAddr = ui32BaseAddr + SGX_REGS_OFFSET;
+#endif
+       gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+       gsSGXDeviceMap.ui32RegsSize = SGX_REG_SIZE;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+       gsSGXDeviceMap.ui32Flags = SGX_HOSTPORT_PRESENT;
+       gsSGXDeviceMap.sHPSysPBase.uiAddr = ui32HostPortAddr;
+       gsSGXDeviceMap.sHPCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sHPSysPBase);
+       gsSGXDeviceMap.ui32HPSize = SYS_SGX_HP_SIZE;
+#endif
+
+#if defined(MRST_SLAVEPORT)
+
+       gsSGXDeviceMap.sSPSysPBase.uiAddr = ui32BaseAddr + MRST_SGX_SP_OFFSET;
+       gsSGXDeviceMap.sSPCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sSPSysPBase);
+       gsSGXDeviceMap.ui32SPSize = SGX_SP_SIZE;
+#endif
+
+
+
+       gsSGXDeviceMap.sLocalMemSysPBase.uiAddr = 0;
+       gsSGXDeviceMap.sLocalMemDevPBase.uiAddr = 0;
+       gsSGXDeviceMap.sLocalMemCpuPBase.uiAddr = 0;
+       gsSGXDeviceMap.ui32LocalMemSize = 0;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+    gsSGXDeviceMap.sExtSysCacheRegsDevPBase.uiAddr = SYS_EXT_SYS_CACHE_GBL_INV_REG_OFFSET;
+       gsSGXDeviceMap.ui32ExtSysCacheRegsSize = SGX_EXT_SYSTEM_CACHE_REGS_SIZE;
+
+    MDFLD_GL3_WRITE(gsSGXDeviceMap.sExtSysCacheRegsDevPBase.uiAddr, MDFLD_GL3_USE_WRT_INVAL);
+#endif
+
+
+#if !defined(NO_HARDWARE)
+
+       {
+               IMG_SYS_PHYADDR sPoulsboRegsCpuPBase;
+               sPoulsboRegsCpuPBase.uiAddr = ui32BaseAddr + POULSBO_REGS_OFFSET;
+               gsPoulsboRegsCPUVaddr = OSMapPhysToLin(SysSysPAddrToCpuPAddr(sPoulsboRegsCpuPBase),
+                                                                                                POULSBO_REG_SIZE,
+                                                                                                PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                                IMG_NULL);
+
+               sPoulsboRegsCpuPBase.uiAddr = ui32BaseAddr + POULSBO_DISPLAY_REGS_OFFSET;
+               gsPoulsboDisplayRegsCPUVaddr = OSMapPhysToLin(SysSysPAddrToCpuPAddr(sPoulsboRegsCpuPBase),
+                                                                                                POULSBO_DISPLAY_REG_SIZE,
+                                                                                                PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                                IMG_NULL);
+       }
+#endif
+#if defined(PDUMP)
+       {
+
+               static IMG_CHAR pszPDumpDevName[] = "SGXMEM";
+               gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName;
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+
+#define VERSION_STR_MAX_LEN_TEMPLATE "SGX revision = 000.000.000"
+static PVRSRV_ERROR SysCreateVersionString(SYS_DATA *psSysData)
+{
+    IMG_UINT32 ui32MaxStrLen;
+    PVRSRV_ERROR eError;
+    IMG_INT32 i32Count;
+    IMG_CHAR *pszVersionString;
+    IMG_UINT32 ui32SGXRevision = 0;
+       IMG_VOID *pvSGXRegs;
+
+       pvSGXRegs = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+                                                                                        gsSGXDeviceMap.ui32RegsSize,
+                                                                                        PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                        IMG_NULL);
+
+       if (pvSGXRegs != IMG_NULL)
+       {
+            ui32SGXRevision = OSReadHWReg(pvSGXRegs, EUR_CR_CORE_REVISION);
+            OSUnMapPhysToLin(pvSGXRegs,
+                                                                                               gsSGXDeviceMap.ui32RegsSize,
+                                                                                               PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                               IMG_NULL);
+       }
+       else
+       {
+            PVR_DPF((PVR_DBG_ERROR,"SysCreateVersionString: Couldn't map SGX registers"));
+       }
+
+    ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+    eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                          ui32MaxStrLen + 1,
+                          (IMG_PVOID *)&pszVersionString,
+                          IMG_NULL,
+                         "Version String");
+    if(eError != PVRSRV_OK)
+    {
+               return eError;
+    }
+
+    i32Count = OSSNPrintf(pszVersionString, ui32MaxStrLen + 1,
+                           "SGX revision = %u.%u.%u",
+                           (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MAJOR_MASK)
+                            >> EUR_CR_CORE_REVISION_MAJOR_SHIFT),
+                           (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MINOR_MASK)
+                            >> EUR_CR_CORE_REVISION_MINOR_SHIFT),
+                           (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MAINTENANCE_MASK)
+                            >> EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT)
+                           );
+    if(i32Count == -1)
+    {
+        ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+        OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                    ui32MaxStrLen + 1,
+                    pszVersionString,
+                    IMG_NULL);
+
+               return PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    psSysData->pszVersionString = pszVersionString;
+
+    return PVRSRV_OK;
+}
+
+static IMG_VOID SysFreeVersionString(SYS_DATA *psSysData)
+{
+    if(psSysData->pszVersionString)
+    {
+        IMG_UINT32 ui32MaxStrLen;
+        ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+        OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                    ui32MaxStrLen+1,
+                    psSysData->pszVersionString,
+                    IMG_NULL);
+               psSysData->pszVersionString = IMG_NULL;
+    }
+}
+
+PVRSRV_ERROR SysInitialise(IMG_VOID)
+{
+       IMG_UINT32                      i                         = 0;
+       PVRSRV_ERROR            eError;
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       SGX_TIMING_INFORMATION* psTimingInfo;
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+       gpsSysData = &gsSysData;
+       OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
+
+       gpsSysData->pvSysSpecificData = &gsSysSpecificData;
+       gsSysSpecificData.ui32SysSpecificData = 0;
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM)
+
+       PVR_ASSERT(gpsPVRLDMDev != IMG_NULL);
+       gsSysSpecificData.psPCIDev = gpsPVRLDMDev;
+#endif
+
+       eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+
+
+       psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
+       psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+       psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       psTimingInfo->bEnableActivePM = (drm_psb_ospm != 0);
+       /*printk(KERN_ERR "SGX APM is %s\n", (drm_psb_ospm != 0)? "enabled":"disabled"); */
+#else
+       psTimingInfo->bEnableActivePM = IMG_FALSE;
+#endif
+       psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
+       psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
+
+       eError = PCIInitDev(gpsSysData);
+       if (eError != PVRSRV_OK)
+       {
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+
+       gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT;
+
+
+       for(i=0; i<SYS_DEVICE_COUNT; i++)
+       {
+               gpsSysData->sDeviceID[i].uiID = i;
+               gpsSysData->sDeviceID[i].bInUse = IMG_FALSE;
+       }
+
+       gpsSysData->psDeviceNodeList = IMG_NULL;
+       gpsSysData->psQueueList = IMG_NULL;
+
+       eError = SysInitialiseCommon(gpsSysData);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+
+
+
+
+
+       eError = SysLocateDevices(gpsSysData);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+
+
+
+
+       eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice,
+                                                                 DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+
+
+       /* register MSVDX, with 0 interrupt bit, no interrupt will be served */
+       eError = PVRSRVRegisterDevice(gpsSysData, MSVDXRegisterDevice,
+                                     DEVICE_MSVDX_INTERRUPT, &gui32MRSTMSVDXDeviceID);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register MSVDXdevice!"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+
+       if (!dev_priv->topaz_disabled)
+       {
+               /* register TOPAZ, with 0 interrupt bit, no interrupt will be served */
+               eError = PVRSRVRegisterDevice(gpsSysData, TOPAZRegisterDevice,
+                                             DEVICE_TOPAZ_INTERRUPT, &gui32MRSTTOPAZDeviceID);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register TOPAZdevice!"));
+                       SysDeinitialise(gpsSysData);
+                       gpsSysData = IMG_NULL;
+                       return eError;
+               }
+       }
+
+       psDeviceNode = gpsSysData->psDeviceNodeList;
+
+       while(psDeviceNode)
+       {
+
+               switch(psDeviceNode->sDevId.eDeviceType)
+               {
+                       case PVRSRV_DEVICE_TYPE_SGX:
+                       {
+                               DEVICE_MEMORY_INFO *psDevMemoryInfo;
+                               DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+                               psDeviceNode->psLocalDevMemArena = IMG_NULL;
+
+
+                               psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+                               psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+                               for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
+                               {
+                                       psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+#ifdef OEM_CUSTOMISE
+
+#endif
+                               }
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+                               gpsSGXDevNode = psDeviceNode;
+#endif
+                               break;
+                       }
+                       case PVRSRV_DEVICE_TYPE_MSVDX:
+                       /* nothing need to do here */
+                       break;
+                       case PVRSRV_DEVICE_TYPE_TOPAZ:
+                       break;
+                       default:
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!"));
+                               return PVRSRV_ERROR_INIT_FAILURE;
+                       }
+               }
+
+
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       PDUMPINIT();
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PDUMP_INIT);
+
+
+       eError = PVRSRVInitialiseDevice (gui32SGXDeviceID);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_SGX_INITIALISED);
+
+       eError = PVRSRVInitialiseDevice (gui32MRSTMSVDXDeviceID);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+
+       if (!dev_priv->topaz_disabled)
+       {
+               eError = PVRSRVInitialiseDevice (gui32MRSTTOPAZDeviceID);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+                       SysDeinitialise(gpsSysData);
+                       gpsSysData = IMG_NULL;
+                       return eError;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static IMG_VOID SysEnableInterrupts(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+       IMG_UINT32 ui32RegData;
+       IMG_UINT32 ui32Mask;
+
+       ui32Mask = POULSBO_THALIA_MASK;
+
+
+       ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG);
+       OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG, ui32RegData | ui32Mask);
+
+
+       ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_MASK_REG);
+       OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_MASK_REG, ui32RegData & (~ui32Mask));
+
+
+       ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG);
+       OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG, ui32RegData | ui32Mask);
+
+       PVR_DPF((PVR_DBG_MESSAGE, "SysEnableInterrupts: Interrupts enabled"));
+#endif
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+}
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static IMG_VOID SysDisableInterrupts(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+       IMG_UINT32 ui32RegData;
+       IMG_UINT32 ui32Mask;
+       ui32Mask = POULSBO_THALIA_MASK;
+
+
+       ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG);
+       OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG, ui32RegData & (~ui32Mask));
+
+
+       ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_MASK_REG);
+       OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_MASK_REG, ui32RegData | ui32Mask);
+
+       PVR_TRACE(("SysDisableInterrupts: Interrupts disabled"));
+#endif
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+}
+#endif
+
+PVRSRV_ERROR SysFinalise(IMG_VOID)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       eError = OSInstallMISR(gpsSysData);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysFinalise: OSInstallMISR failed"));
+               return eError;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_MISR_INSTALLED);
+
+#if defined(SYS_USING_INTERRUPTS) && !defined(SUPPORT_DRI_DRM_EXT)
+       eError = OSInstallSystemLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysFinalise: OSInstallSystemLISR failed"));
+               return eError;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED);
+#endif
+
+#if (defined(SYS_USING_INTERRUPTS) && !defined(SUPPORT_DRI_DRM_EXT))
+       SysEnableInterrupts(gpsSysData);
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+#endif
+
+       eError = SysCreateVersionString(gpsSysData);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to create a system version string"));
+       }
+       else
+       {
+           PVR_DPF((PVR_DBG_WARNING, "SysFinalise: Version string: %s", gpsSysData->pszVersionString));
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR SysDeinitialise (SYS_DATA *psSysData)
+{
+       PVRSRV_ERROR eError;
+
+       SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+#if (defined(SYS_USING_INTERRUPTS) && !defined(SUPPORT_DRI_DRM_EXT))
+       if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+       {
+               SysDisableInterrupts(psSysData);
+       }
+#endif
+
+#if defined(SYS_USING_INTERRUPTS) && !defined(SUPPORT_DRI_DRM_EXT)
+       if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_LISR_INSTALLED))
+       {
+               eError = OSUninstallSystemLISR(psSysData);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallSystemLISR failed"));
+                       return eError;
+               }
+       }
+#endif
+       if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_MISR_INSTALLED))
+       {
+               eError = OSUninstallMISR(psSysData);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallMISR failed"));
+                       return eError;
+               }
+       }
+
+       if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_SGX_INITIALISED))
+       {
+
+               eError = PVRSRVDeinitialiseDevice(gui32SGXDeviceID);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device"));
+                       return eError;
+               }
+       }
+
+       SysFreeVersionString(psSysData);
+
+       PCIDeInitDev(psSysData);
+
+       eError = OSDeInitEnvData(psSysData->pvEnvSpecificData);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init env structure"));
+               return eError;
+       }
+
+       SysDeinitialiseCommon(gpsSysData);
+
+
+#if !defined(NO_HARDWARE)
+
+       OSUnMapPhysToLin(gsPoulsboRegsCPUVaddr,
+                                                                                        POULSBO_REG_SIZE,
+                                                                                        PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                        IMG_NULL);
+
+       OSUnMapPhysToLin(gsPoulsboDisplayRegsCPUVaddr,
+                                                                                        POULSBO_DISPLAY_REG_SIZE,
+                                                                                        PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                        IMG_NULL);
+#endif
+       if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PDUMP_INIT))
+       {
+               PDUMPDEINIT();
+       }
+
+       gpsSysData = IMG_NULL;
+
+       return PVRSRV_OK;
+}
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA* psSysData,
+               PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if !defined(SUPPORT_DRI_DRM_EXT)
+       IMG_UINT32 ui32Devices = 0;
+       IMG_UINT32 ui32Data, ui32DIMMask;
+
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+       ui32Data = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG);
+
+       if (ui32Data & POULSBO_THALIA_MASK)
+       {
+               ui32Devices |= DEVICE_SGX_INTERRUPT;
+       }
+
+       if (ui32Data & POULSBO_MSVDX_MASK)
+       {
+               ui32Devices |= DEVICE_MSVDX_INTERRUPT;
+       }
+
+
+       ui32DIMMask = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG);
+       ui32DIMMask &= ~(POULSBO_THALIA_MASK | POULSBO_MSVDX_MASK);
+
+
+       if (ui32Data & ui32DIMMask)
+       {
+               ui32Devices |= DEVICE_DISP_INTERRUPT;
+       }
+
+       return (ui32Devices);
+#else
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+       return 0;
+#endif
+}
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
+{
+#if !defined(SUPPORT_DRI_DRM_EXT)
+       IMG_UINT32 ui32Data;
+       IMG_UINT32 ui32Mask = 0;
+
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+
+       ui32Data = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG);
+
+       if ((ui32ClearBits & DEVICE_SGX_INTERRUPT) &&
+                       (ui32Data & POULSBO_THALIA_MASK))
+       {
+               ui32Mask |= POULSBO_THALIA_MASK;
+       }
+
+       if ((ui32ClearBits & DEVICE_MSVDX_INTERRUPT) &&
+                       (ui32Data & POULSBO_MSVDX_MASK))
+       {
+               ui32Mask |= POULSBO_MSVDX_MASK;
+       }
+
+       if ((ui32ClearBits & DEVICE_DISP_INTERRUPT) &&
+                       (ui32Data & POULSBO_VSYNC_PIPEA_VBLANK_MASK))
+       {
+               ui32Mask |= POULSBO_VSYNC_PIPEA_VBLANK_MASK;
+       }
+
+       if (ui32Mask)
+       {
+               OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG, ui32Mask);
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+       PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+#endif
+}
+
+
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+                                                                       IMG_VOID **ppvDeviceMap)
+{
+       switch(eDeviceType)
+       {
+               case PVRSRV_DEVICE_TYPE_SGX:
+               {
+
+                       *ppvDeviceMap = (IMG_VOID*)&gsSGXDeviceMap;
+                       break;
+               }
+               default:
+               {
+                       PVR_DPF((PVR_DBG_ERROR,"SysGetDeviceMemoryMap: unsupported device type"));
+               }
+       }
+       return PVRSRV_OK;
+}
+
+
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType,
+                                                                               IMG_CPU_PHYADDR CpuPAddr)
+{
+       IMG_DEV_PHYADDR DevPAddr;
+
+       PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+       DevPAddr.uiAddr = CpuPAddr.uiAddr;
+
+       return DevPAddr;
+}
+
+
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR sys_paddr)
+{
+       IMG_CPU_PHYADDR cpu_paddr;
+
+
+       cpu_paddr.uiAddr = sys_paddr.uiAddr;
+       return cpu_paddr;
+}
+
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr)
+{
+       IMG_SYS_PHYADDR sys_paddr;
+
+
+       sys_paddr.uiAddr = cpu_paddr.uiAddr;
+       return sys_paddr;
+}
+
+
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr)
+{
+    IMG_DEV_PHYADDR DevPAddr;
+
+       PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+    DevPAddr.uiAddr = SysPAddr.uiAddr;
+
+    return DevPAddr;
+}
+
+
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR DevPAddr)
+{
+    IMG_SYS_PHYADDR SysPAddr;
+
+       PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+    SysPAddr.uiAddr = DevPAddr.uiAddr;
+
+    return SysPAddr;
+}
+
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+  psDeviceNode->ui32SOCInterruptBit = DEVICE_DISP_INTERRUPT;
+}
+
+
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+PVRSRV_ERROR SysOEMFunction (  IMG_UINT32      ui32ID,
+                                                               IMG_VOID        *pvIn,
+                                                               IMG_UINT32  ulInSize,
+                                                               IMG_VOID        *pvOut,
+                                                               IMG_UINT32      ulOutSize)
+{
+       PVR_UNREFERENCED_PARAMETER(ulInSize);
+       PVR_UNREFERENCED_PARAMETER(pvIn);
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+       if ((ui32ID == OEM_GET_EXT_FUNCS) &&
+               (ulOutSize == sizeof(PVRSRV_DC_OEM_JTABLE)))
+       {
+               PVRSRV_DC_OEM_JTABLE *psOEMJTable = (PVRSRV_DC_OEM_JTABLE*)pvOut;
+               psOEMJTable->pfnOEMBridgeDispatch = &PVRSRV_BridgeDispatchKM;
+
+               psOEMJTable->pfnOEMReadRegistryString  = IMG_NULL;
+               psOEMJTable->pfnOEMWriteRegistryString = IMG_NULL;
+
+               return PVRSRV_OK;
+       }
+#endif
+
+       return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+static PVRSRV_ERROR SysMapInRegisters(IMG_VOID)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNodeList;
+
+       psDeviceNodeList = gpsSysData->psDeviceNodeList;
+
+       while (psDeviceNodeList)
+       {
+               switch(psDeviceNodeList->sDevId.eDeviceType)
+               {
+               case PVRSRV_DEVICE_TYPE_SGX:
+               {
+                       PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNodeList->pvDevice;
+
+                       if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS))
+                       {
+                               psDevInfo->pvRegsBaseKM = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+                                                                        gsSGXDeviceMap.ui32RegsSize,
+                                                                        PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                        IMG_NULL);
+
+                               if (!psDevInfo->pvRegsBaseKM)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR,"SysMapInRegisters : Failed to map in SGX registers\n"));
+                                       return PVRSRV_ERROR_BAD_MAPPING;
+                               }
+                               SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS);
+                       }
+                       psDevInfo->ui32RegSize   = gsSGXDeviceMap.ui32RegsSize;
+                       psDevInfo->sRegsPhysBase = gsSGXDeviceMap.sRegsSysPBase;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+                       if (gsSGXDeviceMap.ui32Flags & SGX_HOSTPORT_PRESENT)
+                       {
+                               if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP))
+                               {
+
+                                       psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(gsSGXDeviceMap.sHPCpuPBase,
+                                                                                                                    gsSGXDeviceMap.ui32HPSize,
+                                                                                                                    PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                                                                                    IMG_NULL);
+                                       if (!psDevInfo->pvHostPortBaseKM)
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR,"SysMapInRegisters : Failed to map in host port\n"));
+                                               return PVRSRV_ERROR_BAD_MAPPING;
+                                       }
+                                       SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP);
+                               }
+                               psDevInfo->ui32HPSize  = gsSGXDeviceMap.ui32HPSize;
+                               psDevInfo->sHPSysPAddr = gsSGXDeviceMap.sHPSysPBase;
+                       }
+#endif
+                       break;
+               }
+               default:
+                       break;
+               }
+               psDeviceNodeList = psDeviceNodeList->psNext;
+       }
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR SysUnmapRegisters(IMG_VOID)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNodeList;
+
+       psDeviceNodeList = gpsSysData->psDeviceNodeList;
+
+       while (psDeviceNodeList)
+       {
+               switch (psDeviceNodeList->sDevId.eDeviceType)
+               {
+               case PVRSRV_DEVICE_TYPE_SGX:
+               {
+                       PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNodeList->pvDevice;
+#if !(defined(NO_HARDWARE) && defined(__linux__))
+
+                       if (psDevInfo->pvRegsBaseKM)
+                       {
+                               OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+                                                gsSGXDeviceMap.ui32RegsSize,
+                                                PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                IMG_NULL);
+
+                               SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS);
+                       }
+#endif
+
+                       psDevInfo->pvRegsBaseKM = IMG_NULL;
+                       psDevInfo->ui32RegSize          = 0;
+                       psDevInfo->sRegsPhysBase.uiAddr = 0;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+                       if (gsSGXDeviceMap.ui32Flags & SGX_HOSTPORT_PRESENT)
+                       {
+
+                               if (psDevInfo->pvHostPortBaseKM)
+                               {
+                                       OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
+                                                        gsSGXDeviceMap.ui32HPSize,
+                                                        PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                                                        IMG_NULL);
+
+                                       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP);
+
+                                       psDevInfo->pvHostPortBaseKM = IMG_NULL;
+                               }
+
+                               psDevInfo->ui32HPSize  = 0;
+                               psDevInfo->sHPSysPAddr.uiAddr = 0;
+                       }
+#endif
+                       break;
+               }
+               default:
+                       break;
+               }
+               psDeviceNodeList = psDeviceNodeList->psNext;
+       }
+
+#if !(defined(NO_HARDWARE) && defined(__linux__))
+
+       OSUnMapPhysToLin(gsPoulsboRegsCPUVaddr,
+                               POULSBO_REG_SIZE,
+                               PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                               IMG_NULL);
+
+
+       OSUnMapPhysToLin(gsPoulsboDisplayRegsCPUVaddr,
+                               POULSBO_DISPLAY_REG_SIZE,
+                               PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                               IMG_NULL);
+
+#endif
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError= PVRSRV_OK;
+       PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)(gsSysSpecificData.hSGXPCI);
+
+       if (eNewPowerState != gpsSysData->eCurrentPowerState)
+       {
+               if ((eNewPowerState == PVRSRV_SYS_POWER_STATE_D3) &&
+                       (gpsSysData->eCurrentPowerState < PVRSRV_SYS_POWER_STATE_D3))
+               {
+#if !defined(SUPPORT_DRI_DRM_EXT)
+                       drm_irq_uninstall(gpDrmDevice);
+#endif
+
+                       SysUnmapRegisters();
+
+                       //Save some pci state that won't get saved properly by pci_save_state()
+                       pci_read_config_dword(psPVRPCI->psPCIDev, 0x5C, &gsSysSpecificData.saveBSM);
+                       pci_read_config_dword(psPVRPCI->psPCIDev, 0xFC, &gsSysSpecificData.saveVBT);
+                       pci_read_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_ADDR_LOC, &gsSysSpecificData.msi_addr);
+                       pci_read_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_DATA_LOC, &gsSysSpecificData.msi_data);
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+                       eError = OSPCISuspendDev(gsSysSpecificData.hSGXPCI);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SysSystemPrePowerState: OSPCISuspendDev failed (%d)", eError));
+                       }
+#endif
+               }
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)(gsSysSpecificData.hSGXPCI);
+
+       if (eNewPowerState != gpsSysData->eCurrentPowerState)
+       {
+               if ((gpsSysData->eCurrentPowerState == PVRSRV_SYS_POWER_STATE_D3) &&
+                       (eNewPowerState < PVRSRV_SYS_POWER_STATE_D3))
+               {
+#if !defined(SUPPORT_DRI_DRM_EXT)
+                       eError = OSPCIResumeDev(gsSysSpecificData.hSGXPCI);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: OSPCIResumeDev failed (%d)", eError));
+                               return eError;
+                       }
+#endif
+
+                       //Restore some pci state that will not have gotten restored properly by pci_restore_state()
+                       pci_write_config_dword(psPVRPCI->psPCIDev, 0x5c, gsSysSpecificData.saveBSM);
+                       pci_write_config_dword(psPVRPCI->psPCIDev, 0xFC, gsSysSpecificData.saveVBT);
+                       pci_write_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_ADDR_LOC, gsSysSpecificData.msi_addr);
+                       pci_write_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_DATA_LOC, gsSysSpecificData.msi_data);
+
+                       eError = SysLocateDevices(gpsSysData);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: Failed to locate devices"));
+                               return eError;
+                       }
+
+                       eError = SysMapInRegisters();
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: Failed to map in registers"));
+                               return eError;
+                       }
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+                       drm_irq_install(gpDrmDevice);
+#endif
+               }
+       }
+       return eError;
+}
+
+
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32                 ui32DeviceIndex,
+                                                                       PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                                                                       PVRSRV_DEV_POWER_STATE  eCurrentPowerState)
+{
+       if ((eNewPowerState != eCurrentPowerState) &&
+           (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+       {
+               if (ui32DeviceIndex == gui32SGXDeviceID)
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Remove SGX power"));
+#if defined(SUPPORT_DRI_DRM_EXT)
+                       psb_irq_uninstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+                       ospm_power_island_down(OSPM_GRAPHICS_ISLAND);
+                       ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+#endif
+               }
+#if 1
+               else if (ui32DeviceIndex == gui32MRSTMSVDXDeviceID)
+               {
+                       if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+                               ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+                       } else {
+                               ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+                               ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+                               ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+                       }
+#if 0
+#if defined(SUPPORT_DRI_DRM_EXT)
+                       ospm_power_using_hw_end(OSPM_VIDEO_DEC_ISLAND);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+#endif
+#endif
+               }
+               else if (ui32DeviceIndex == gui32MRSTTOPAZDeviceID)
+               {
+                       if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+                               ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+                       } else {
+                               ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+                               ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+                               ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+                       }
+               }
+#if 0
+#if defined(SUPPORT_DRI_DRM_EXT)
+                       ospm_power_using_hw_end(OSPM_VIDEO_ENC_ISLAND);
+                       ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+#endif
+#endif
+#endif
+       }
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32                        ui32DeviceIndex,
+                                                                        PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                                                        PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+       if ((eNewPowerState != eCurrentPowerState) &&
+           (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+       {
+               if (ui32DeviceIndex == gui32SGXDeviceID)
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore SGX power"));
+#if defined(SUPPORT_DRI_DRM_EXT)
+                       ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true);
+#endif
+
+               }
+#if 1
+               else if (ui32DeviceIndex == gui32MRSTMSVDXDeviceID)
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore MSVDX power"));
+                       if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+                               ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+                       } else {
+                               ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+                               ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+                               ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+                       }
+#if 0
+#if defined(SUPPORT_DRI_DRM_EXT)
+                       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+                       {
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+
+                       if (!ospm_power_using_hw_begin(OSPM_VIDEO_DEC_ISLAND, true))
+                       {
+                               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+#endif
+#endif
+               }
+               else if (ui32DeviceIndex == gui32MRSTTOPAZDeviceID)
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore TOPAZ power"));
+                       if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+                               ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+                       } else {
+                               ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+                               ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+                               ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+                       }
+#if 0
+#if defined(SUPPORT_DRI_DRM_EXT)
+                       if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+                       {
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+
+                       if (!ospm_power_using_hw_begin(OSPM_VIDEO_ENC_ISLAND, true))
+                       {
+                               ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+#endif
+#endif
+               }
+#endif
+       }
+
+       return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+int SYSPVRServiceSGXInterrupt(struct drm_device *dev)
+{
+       IMG_BOOL bStatus = IMG_FALSE;
+
+       PVR_UNREFERENCED_PARAMETER(dev);
+
+       if (gpsSGXDevNode != IMG_NULL)
+       {
+               bStatus = (*gpsSGXDevNode->pfnDeviceISR)(gpsSGXDevNode->pvISRData);
+               if (bStatus)
+               {
+                       OSScheduleMISR((IMG_VOID *)gpsSGXDevNode->psSysData);
+               }
+       }
+
+       return bStatus ? 1 : 0;
+}
+#endif
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/sysconfig.h b/drivers/staging/mrst/pvr/services4/system/unified/sysconfig.h
new file mode 100644 (file)
index 0000000..6530f28
--- /dev/null
@@ -0,0 +1,155 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__SOCCONFIG_H__)
+#define __SOCCONFIG_H__
+#include "syscommon.h"
+#include "extsyscache.h"
+
+#define VS_PRODUCT_NAME        "SGX Medfield"
+
+#define SYS_NO_POWER_LOCK_TIMEOUT
+
+/*#define SGX_FEATURE_HOST_PORT */
+
+#define SYS_SGX_USSE_COUNT                                     (2)
+
+#define POULSBO_REGS_OFFSET    0x00000
+#define POULSBO_REG_SIZE       0x2100  
+
+#define SGX_REGS_OFFSET                0x80000
+#define PSB_SGX_REGS_OFFSET    0x40000
+#define SGX_REG_SIZE           0x4000
+#define MSVDX_REGS_OFFSET      0x50000
+
+#ifdef SUPPORT_MSVDX
+#define        POULSBO_MAX_OFFSET      (MSVDX_REGS_OFFSET + MSVDX_REG_SIZE)
+#else
+#define        POULSBO_MAX_OFFSET      (SGX_REGS_OFFSET + SGX_REG_SIZE)
+#define        PSB_POULSBO_MAX_OFFSET  (PSB_SGX_REGS_OFFSET + SGX_REG_SIZE)
+#endif
+
+#define SYS_SGX_DEV_VENDOR_ID          0x8086
+#define PSB_SYS_SGX_DEV_DEVICE_ID_1    0x8108
+#define PSB_SYS_SGX_DEV_DEVICE_ID_2    0x8109
+
+#define SYS_SGX_DEV_DEVICE_ID          0x4102
+
+#define SYS_SGX_DEVICE_IDS \
+    {0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108}, \
+    {0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109}, \
+    {0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+    {0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+    {0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+    {0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+    {0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+    {0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+    {0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+    {0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+    {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+    {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+    {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+    {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+    {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+    {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+    {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+    {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+    {0, 0, 0}
+
+
+#define MMADR_INDEX                    4
+#define IOPORT_INDEX           5
+#define GMADR_INDEX                    6
+#define MMUADR_INDEX           7
+#define FBADR_INDEX                    23
+#define FBSIZE_INDEX           24
+
+#define DISPLAY_SURFACE_SIZE        (4 * 1024 * 1024)
+
+#define DEVICE_SGX_INTERRUPT           (1<<0)
+#define DEVICE_MSVDX_INTERRUPT         (1<<1)
+#define DEVICE_DISP_INTERRUPT          (1<<2)
+#define DEVICE_TOPAZ_INTERRUPT         (1<<3)
+
+#define POULSBO_INTERRUPT_ENABLE_REG           0x20A0
+#define POULSBO_INTERRUPT_IDENTITY_REG         0x20A4
+#define POULSBO_INTERRUPT_MASK_REG                     0x20A8
+#define POULSBO_INTERRUPT_STATUS_REG           0x20AC
+
+#define POULSBO_DISP_MASK                                      (1<<17)
+#define POULSBO_THALIA_MASK                                    (1<<18)
+#define POULSBO_MSVDX_MASK                                     (1<<19)
+#define POULSBO_VSYNC_PIPEA_VBLANK_MASK                (1<<7)
+#define POULSBO_VSYNC_PIPEA_EVENT_MASK         (1<<6)
+#define POULSBO_VSYNC_PIPEB_VBLANK_MASK                (1<<5)
+#define POULSBO_VSYNC_PIPEB_EVENT_MASK         (1<<4)
+
+#define POULSBO_DISPLAY_REGS_OFFSET                    0x70000
+#define POULSBO_DISPLAY_REG_SIZE                       0x2000          
+
+#define POULSBO_DISPLAY_A_CONFIG                       0x00008
+#define POULSBO_DISPLAY_A_STATUS_SELECT                0x00024
+#define POULSBO_DISPLAY_B_CONFIG                       0x01008
+#define POULSBO_DISPLAY_B_STATUS_SELECT                0x01024
+
+#define POULSBO_DISPLAY_PIPE_ENABLE                    (1<<31)
+#define POULSBO_DISPLAY_VSYNC_STS_EN           (1<<25)
+#define POULSBO_DISPLAY_VSYNC_STS                      (1<<9)
+
+#if defined(SGX_FEATURE_HOST_PORT)
+       #define SYS_SGX_HP_SIZE         0x8000000
+       #define PSB_SYS_SGX_HP_SIZE     0x4000000
+       
+       #define SYS_SGX_HOSTPORT_BASE_DEVVADDR 0xD0000000
+       #if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030)
+               
+
+
+               #define SYS_SGX_HOSTPORT_BRN23030_OFFSET 0x7C00000
+       #endif
+#endif
+
+typedef struct
+{
+       union
+       {
+#if !defined(VISTA)
+               IMG_UINT8       aui8PCISpace[256];
+               IMG_UINT16      aui16PCISpace[128];
+               IMG_UINT32      aui32PCISpace[64];
+#endif
+               struct  
+               {
+                       IMG_UINT16      ui16VenID;
+                       IMG_UINT16      ui16DevID;
+                       IMG_UINT16      ui16PCICmd;
+                       IMG_UINT16      ui16PCIStatus;
+               }s;
+       }u;
+} PCICONFIG_SPACE, *PPCICONFIG_SPACE;
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/sysinfo.h b/drivers/staging/mrst/pvr/services4/system/unified/sysinfo.h
new file mode 100644 (file)
index 0000000..6e113c9
--- /dev/null
@@ -0,0 +1,43 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+#define MAX_HW_TIME_US                         (500000)
+#define WAIT_TRY_COUNT                         (10000)
+
+typedef enum _SYS_DEVICE_TYPE_
+{
+       SYS_DEVICE_SGX                                          = 0,
+
+       SYS_DEVICE_FORCE_I16                            = 0x7fff
+
+} SYS_DEVICE_TYPE;
+
+#define SYS_DEVICE_COUNT 10
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/syslocal.h b/drivers/staging/mrst/pvr/services4/system/unified/syslocal.h
new file mode 100644 (file)
index 0000000..6fb68c4
--- /dev/null
@@ -0,0 +1,83 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#if !defined(__SYSLOCAL_H__)
+#define __SYSLOCAL_H__
+
+#define SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV              0x00000001
+#define SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE   0x00000002
+#define SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE  0x00000004
+#if defined(NO_HARDWARE)
+#define SYS_SPECIFIC_DATA_ALLOC_DUMMY_SGX_REGS         0x00000008
+#if defined(SUPPORT_MSVDX)
+#define        SYS_SPECIFIC_DATA_ALLOC_DUMMY_MSVDX_REGS        0x00000020
+#endif 
+#endif 
+#define        SYS_SPECIFIC_DATA_SGX_INITIALISED               0x00000040
+#if defined(SUPPORT_MSVDX)
+#define        SYS_SPECIFIC_DATA_MSVDX_INITIALISED             0x00000080
+#endif 
+#define        SYS_SPECIFIC_DATA_MISR_INSTALLED                0x00000100
+#define        SYS_SPECIFIC_DATA_LISR_INSTALLED                0x00000200
+#define        SYS_SPECIFIC_DATA_PDUMP_INIT                    0x00000400
+#define        SYS_SPECIFIC_DATA_IRQ_ENABLED                   0x00000800
+
+#define        SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS             0x00001000
+#define        SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP               0x00004000
+#define        SYS_SPECIFIC_DATA_PM_UNMAP_MSVDX_REGS           0x00008000
+#define        SYS_SPECIFIC_DATA_PM_IRQ_DISABLE                0x00010000
+#define        SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR             0x00020000
+
+#define        SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData |= (flag)))
+
+#define        SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData &= ~(flag)))
+
+#define        SYS_SPECIFIC_DATA_TEST(psSysSpecData, flag) (((psSysSpecData)->ui32SysSpecificData & (flag)) != 0)
+typedef struct _SYS_SPECIFIC_DATA_TAG_
+{
+       
+       IMG_UINT32 ui32SysSpecificData;
+#ifdef __linux__
+       PVRSRV_PCI_DEV_HANDLE hSGXPCI;
+#endif
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM_EXT)
+       struct pci_dev *psPCIDev;
+#endif
+
+       /* MSI reg save */
+       uint32_t msi_addr;
+       uint32_t msi_data;
+
+       uint32_t saveBSM;
+       uint32_t saveVBT;
+} SYS_SPECIFIC_DATA;
+
+#endif 
+
+
diff --git a/drivers/staging/mrst/pvr/services4/system/unified/sysutils.c b/drivers/staging/mrst/pvr/services4/system/unified/sysutils.c
new file mode 100644 (file)
index 0000000..b89a1da
--- /dev/null
@@ -0,0 +1,30 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "sysinfo.h"
+#include "syslocal.h"
+
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/client/linuxsrv.h b/drivers/staging/mrst/pvr/tools/intern/debug/client/linuxsrv.h
new file mode 100644 (file)
index 0000000..adfcd75
--- /dev/null
@@ -0,0 +1,48 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _LINUXSRV_H__
+#define _LINUXSRV_H__
+
+typedef struct tagIOCTL_PACKAGE
+{
+       IMG_UINT32 ui32Cmd;              
+       IMG_UINT32 ui32Size;                       
+       IMG_VOID        *pInBuffer;          
+       IMG_UINT32  ui32InBufferSize;     
+       IMG_VOID    *pOutBuffer;         
+       IMG_UINT32  ui32OutBufferSize;    
+} IOCTL_PACKAGE;
+
+IMG_UINT32 DeviceIoControl(IMG_UINT32 hDevice,         
+                                               IMG_UINT32 ui32ControlCode, 
+                                               IMG_VOID *pInBuffer,            
+                                               IMG_UINT32 ui32InBufferSize,
+                                               IMG_VOID *pOutBuffer,           
+                                               IMG_UINT32 ui32OutBufferSize,  
+                                               IMG_UINT32 *pui32BytesReturned); 
+
+#endif 
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c
new file mode 100644 (file)
index 0000000..1352b71
--- /dev/null
@@ -0,0 +1,2354 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+
+#ifdef LINUX
+#include <linux/string.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+#include "pvr_debug.h"
+
+
+
+
+#define LAST_FRAME_BUF_SIZE    1024
+
+typedef struct _DBG_LASTFRAME_BUFFER_
+{
+       PDBG_STREAM     psStream;
+       IMG_UINT8 ui8Buffer[LAST_FRAME_BUF_SIZE];
+       IMG_UINT32              ui32BufLen;
+       struct _DBG_LASTFRAME_BUFFER_   *psNext;
+} *PDBG_LASTFRAME_BUFFER;
+
+
+static PDBG_STREAM     g_psStreamList = 0;
+static PDBG_LASTFRAME_BUFFER   g_psLFBufferList;
+
+static IMG_UINT32              g_ui32LOff = 0;
+static IMG_UINT32              g_ui32Line = 0;
+static IMG_UINT32              g_ui32MonoLines = 25;
+
+static IMG_BOOL                        g_bHotkeyMiddump = IMG_FALSE;
+static IMG_UINT32              g_ui32HotkeyMiddumpStart = 0xffffffff;
+static IMG_UINT32              g_ui32HotkeyMiddumpEnd = 0xffffffff;
+
+IMG_VOID *                             g_pvAPIMutex=IMG_NULL;
+
+extern IMG_UINT32              g_ui32HotKeyFrame;
+extern IMG_BOOL                        g_bHotKeyPressed;
+extern IMG_BOOL                        g_bHotKeyRegistered;
+
+IMG_BOOL                               gbDumpThisFrame = IMG_FALSE;
+
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream);
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream);
+
+DBGKM_SERVICE_TABLE g_sDBGKMServices =
+{
+       sizeof (DBGKM_SERVICE_TABLE),
+       ExtDBGDrivCreateStream,
+       ExtDBGDrivDestroyStream,
+       ExtDBGDrivFindStream,
+       ExtDBGDrivWriteString,
+       ExtDBGDrivReadString,
+       ExtDBGDrivWrite,
+       ExtDBGDrivRead,
+       ExtDBGDrivSetCaptureMode,
+       ExtDBGDrivSetOutputMode,
+       ExtDBGDrivSetDebugLevel,
+       ExtDBGDrivSetFrame,
+       ExtDBGDrivGetFrame,
+       ExtDBGDrivOverrideMode,
+       ExtDBGDrivDefaultMode,
+       ExtDBGDrivWrite2,
+       ExtDBGDrivWriteStringCM,
+       ExtDBGDrivWriteCM,
+       ExtDBGDrivSetMarker,
+       ExtDBGDrivGetMarker,
+       ExtDBGDrivStartInitPhase,
+       ExtDBGDrivStopInitPhase,
+       ExtDBGDrivIsCaptureFrame,
+       ExtDBGDrivWriteLF,
+       ExtDBGDrivReadLF,
+       ExtDBGDrivGetStreamOffset,
+       ExtDBGDrivSetStreamOffset,
+       ExtDBGDrivIsLastCaptureFrame,
+       ExtDBGDrivWaitForEvent,
+       ExtDBGDrivSetConnectNotifier,
+       ExtDBGDrivWritePersist
+};
+
+
+static IMG_UINT32 DBGDrivWritePersist(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+static IMG_VOID InvalidateAllStreams(IMG_VOID);
+
+
+
+
+DBGKM_CONNECT_NOTIFIER g_fnDBGKMNotifier;
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetConnectNotifier(DBGKM_CONNECT_NOTIFIER fn_notifier)
+{
+       
+       g_fnDBGKMNotifier = fn_notifier;
+}
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *      pszName, IMG_UINT32 ui32CapMode, IMG_UINT32     ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size)
+{
+       IMG_VOID *      pvRet;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       pvRet=DBGDrivCreateStream(pszName, ui32CapMode, ui32OutMode, ui32Flags, ui32Size);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return pvRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivDestroyStream(psStream);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+       IMG_VOID *      pvRet;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       pvRet=DBGDrivFindStream(pszName, bResetStream);
+       if(g_fnDBGKMNotifier.pfnConnectNotifier)
+       {
+               g_fnDBGKMNotifier.pfnConnectNotifier();
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "pfnConnectNotifier not initialised.\n"));
+       }               
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return pvRet;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+       IMG_UINT32      ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret=DBGDrivWriteString(psStream, pszString, ui32Level);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+       IMG_UINT32 ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret=DBGDrivReadString(psStream, pszString, ui32Limit);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+       IMG_UINT32      ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret=DBGDrivWrite(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+       IMG_UINT32 ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret=DBGDrivRead(psStream, bReadInitBuffer, ui32OutBuffSize, pui8OutBuf);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivSetCaptureMode(psStream, ui32Mode, ui32Start, ui32End, ui32SampleRate);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivSetOutputMode(psStream, ui32OutMode);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivSetDebugLevel(psStream, ui32DebugLevel);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivSetFrame(psStream, ui32Frame);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream)
+{
+       IMG_UINT32      ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret=DBGDrivGetFrame(psStream);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+       IMG_BOOL        bRet;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       bRet = DBGDrivIsLastCaptureFrame(psStream);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return bRet;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+       IMG_BOOL        bRet;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       bRet = DBGDrivIsCaptureFrame(psStream, bCheckPreviousFrame);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return bRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivOverrideMode(psStream, ui32Mode);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+void IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivDefaultMode(psStream);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+       IMG_UINT32      ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWritePersist(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+       IMG_UINT32      ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret=DBGDrivWritePersist(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+       if(ui32Ret==0xFFFFFFFFU)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "An error occurred in DBGDrivWritePersist."));
+       }
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+       IMG_UINT32      ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret=DBGDrivWriteStringCM(psStream, pszString, ui32Level);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+       IMG_UINT32      ui32Ret;
+       
+       
+       HostAquireMutex(g_pvAPIMutex);
+       
+       ui32Ret=DBGDrivWriteCM(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+       
+       
+       HostReleaseMutex(g_pvAPIMutex);
+       
+       return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivSetMarker(psStream, ui32Marker);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
+{
+       IMG_UINT32      ui32Marker;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Marker = DBGDrivGetMarker(psStream);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+       IMG_UINT32      ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret = DBGDrivWriteLF(psStream, pui8InBuf, ui32InBuffSize, ui32Level, ui32Flags);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+       IMG_UINT32 ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret = DBGDrivReadLF(psStream, ui32OutBuffSize, pui8OutBuf);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivStartInitPhase(psStream);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivStopInitPhase(psStream);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream)
+{
+       IMG_UINT32 ui32Ret;
+
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret = DBGDrivGetStreamOffset(psStream);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset)
+{
+       
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivSetStreamOffset(psStream, ui32StreamOffset);
+
+       
+       HostReleaseMutex(g_pvAPIMutex);
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+       DBGDrivWaitForEvent(eEvent);
+#else  
+       PVR_UNREFERENCED_PARAMETER(eEvent);                             
+#endif 
+}
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn)
+{
+       IMG_INT         iLen = 0;
+       IMG_UINT32      ui32Value = 0;
+       IMG_UINT32      ui32Digit=1;
+       IMG_UINT32      ui32Base=10;
+       IMG_INT         iPos;
+       IMG_CHAR        bc;
+
+       
+       while (szIn[iLen] > 0)
+       {
+               iLen ++;
+       }
+
+       
+       if (iLen == 0)
+       {
+               return (0);
+       }
+
+       
+       iPos=0;
+       while (szIn[iPos] == '0')
+       {
+               iPos++;
+       }
+       if (szIn[iPos] == '\0')
+       {
+               return 0;
+       }
+       if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
+       {
+               ui32Base=16;
+               szIn[iPos]='0';
+       }
+
+       
+       for (iPos = iLen - 1; iPos >= 0; iPos --)
+       {
+               bc = szIn[iPos];
+
+               if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16)                      
+               {
+                       bc -= 'a' - 0xa;
+               }
+               else
+               if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16)                      
+               {
+                       bc -= 'A' - 0xa;
+               }
+               else
+               if ((bc >= '0') && (bc <= '9'))                         
+               {
+                       bc -= '0';
+               }
+               else
+                       return (0);
+
+               ui32Value += (IMG_UINT32)bc  * ui32Digit;
+
+               ui32Digit = ui32Digit * ui32Base;
+       }
+       return (ui32Value);
+}
+
+
+static IMG_BOOL StreamValid(PDBG_STREAM psStream)
+{
+       PDBG_STREAM     psThis;
+
+       psThis = g_psStreamList;
+
+       while (psThis)
+       {
+               if (psStream && (psThis == psStream))
+               {
+                       return(IMG_TRUE);
+               }
+               else
+               {
+                       psThis = psThis->psNext;
+               }
+       }
+
+       return(IMG_FALSE);
+}
+
+
+static IMG_BOOL StreamValidForRead(PDBG_STREAM psStream)
+{
+       if( StreamValid(psStream) &&
+               ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_WRITEONLY) == 0) )
+       {
+               return(IMG_TRUE);
+       }
+
+       return(IMG_FALSE);
+}
+
+static IMG_BOOL StreamValidForWrite(PDBG_STREAM psStream)
+{
+       if( StreamValid(psStream) &&
+               ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) == 0) )
+       {
+               return(IMG_TRUE);
+       }
+
+       return(IMG_FALSE);
+}
+
+
+static void Write(PDBG_STREAM psStream,IMG_PUINT8 pui8Data,IMG_UINT32 ui32InBuffSize)
+{
+       
+
+       if (!psStream->bCircularAllowed)
+       {
+               
+       }
+
+       if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
+       {
+               
+               IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
+               IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
+
+               
+               HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
+                               (IMG_PVOID) pui8Data,
+                               ui32B1);
+
+               
+               HostMemCopy(psStream->pvBase,
+                               (IMG_PVOID)(pui8Data + ui32B1),
+                               ui32B2);
+
+               
+               psStream->ui32WPtr = ui32B2;
+       }
+       else
+       {       
+               HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
+                               (IMG_PVOID) pui8Data,
+                               ui32InBuffSize);
+
+               psStream->ui32WPtr += ui32InBuffSize;
+
+               if (psStream->ui32WPtr == psStream->ui32Size)
+               {
+                       psStream->ui32WPtr = 0;
+               }
+       }
+       psStream->ui32DataWritten += ui32InBuffSize;
+}
+
+
+void MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine)
+{
+#if defined (_WIN64)
+       PVR_UNREFERENCED_PARAMETER(pszString);
+       PVR_UNREFERENCED_PARAMETER(bNewLine);
+
+#else
+       IMG_UINT32      i;
+       IMG_CHAR *      pScreen;
+
+       pScreen = (IMG_CHAR *) DBGDRIV_MONOBASE;
+
+       pScreen += g_ui32Line * 160;
+
+       
+
+       i=0;
+       do
+       {
+               pScreen[g_ui32LOff + (i*2)] = pszString[i];
+               pScreen[g_ui32LOff + (i*2)+1] = 127;
+               i++;
+       }
+       while ((pszString[i] != 0) && (i < 4096));
+
+       g_ui32LOff += i * 2;
+
+       if (bNewLine)
+       {
+               g_ui32LOff = 0;
+               g_ui32Line++;
+       }
+
+       
+
+       if (g_ui32Line == g_ui32MonoLines)
+       {
+               g_ui32Line = g_ui32MonoLines - 1;
+
+               HostMemCopy((IMG_VOID *)DBGDRIV_MONOBASE,(IMG_VOID *)(DBGDRIV_MONOBASE + 160),160 * (g_ui32MonoLines - 1));
+
+               HostMemSet((IMG_VOID *)(DBGDRIV_MONOBASE + (160 * (g_ui32MonoLines - 1))),0,160);
+       }
+#endif 
+}
+
+static IMG_UINT32 WriteExpandingBuffer(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
+{
+       IMG_UINT ui32Space;
+
+       
+
+       ui32Space = SpaceInStream(psStream);
+
+       
+
+       if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %x is disabled", (IMG_UINTPTR_T) psStream));
+               return(0);
+       }
+
+       
+
+       if (psStream->psCtrl->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
+       {
+               
+
+
+               if (ui32Space < 32)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %x is full and isn't expandable", (IMG_UINTPTR_T) psStream));
+                       return(0);
+               }
+       }
+       else
+       {
+               if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
+               {
+                       IMG_UINT32      ui32NewBufSize;
+
+                       
+
+                       ui32NewBufSize = 2 * psStream->ui32Size;
+
+                       PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanding buffer size = %x, new size = %x",
+                                       psStream->ui32Size, ui32NewBufSize));
+
+                       if (ui32InBuffSize > psStream->ui32Size)
+                       {
+                               ui32NewBufSize += ui32InBuffSize;
+                       }
+
+                       
+
+                       if (!ExpandStreamBuffer(psStream,ui32NewBufSize))
+                       {
+                               if (ui32Space < 32)
+                               {
+                                       if(psStream->bCircularAllowed)
+                                       {
+                                               return(0);
+                                       }
+                                       else
+                                       {
+                                               
+                                               PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: Unable to expand %x. Out of memory.", (IMG_UINTPTR_T) psStream));
+                                               InvalidateAllStreams();
+                                               return (0xFFFFFFFFUL);
+                                       }
+                               }
+                       }
+
+                       
+
+                       ui32Space = SpaceInStream(psStream);
+                       PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanded buffer, free space = %x",
+                                       ui32Space));
+               }
+       }
+
+       
+
+       if (ui32Space <= (ui32InBuffSize + 4))
+       {
+               ui32InBuffSize = ui32Space - 4;
+       }
+
+       
+
+       Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+       if (ui32InBuffSize)
+       {
+               HostSignalEvent(DBG_EVENT_STREAM_DATA);
+       }
+#endif
+       return(ui32InBuffSize);
+}
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *         pszName,
+                                                                  IMG_UINT32   ui32CapMode,
+                                                                  IMG_UINT32   ui32OutMode,
+                                                                  IMG_UINT32   ui32Flags,
+                                                                  IMG_UINT32   ui32Size)
+{
+       PDBG_STREAM psStream;
+       PDBG_STREAM     psInitStream;
+       PDBG_LASTFRAME_BUFFER   psLFBuffer;
+       PDBG_STREAM_CONTROL psCtrl;
+       IMG_UINT32              ui32Off;
+       IMG_VOID *              pvBase; 
+       static IMG_CHAR pszNameInitSuffix[] = "_Init";
+       IMG_UINT32              ui32OffSuffix;
+
+       
+
+
+       psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
+
+       if (psStream)
+       {
+               return ((IMG_VOID *) psStream);
+       }
+
+       
+
+       psStream = HostNonPageablePageAlloc(1);
+       psInitStream = HostNonPageablePageAlloc(1);
+       psLFBuffer = HostNonPageablePageAlloc(1);
+       psCtrl = HostNonPageablePageAlloc(1);
+       if      (
+                       (!psStream) ||
+                       (!psInitStream) ||
+                       (!psLFBuffer) ||
+                       (!psCtrl)
+               )
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
+               return((IMG_VOID *) 0);
+       }
+
+       
+       if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+       {
+               pvBase = HostNonPageablePageAlloc(ui32Size);
+       }
+       else
+       {
+               pvBase = HostPageablePageAlloc(ui32Size);
+       }
+
+       if (!pvBase)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
+               HostNonPageablePageFree(psStream);
+               return((IMG_VOID *) 0);
+       }
+
+       
+       psCtrl->ui32Flags = ui32Flags;
+       psCtrl->ui32CapMode = ui32CapMode;
+       psCtrl->ui32OutMode = ui32OutMode;
+       psCtrl->ui32DebugLevel = DEBUG_LEVEL_0;
+       psCtrl->ui32DefaultMode = ui32CapMode;
+       psCtrl->ui32Start = 0;
+       psCtrl->ui32End = 0;
+       psCtrl->ui32Current = 0;
+       psCtrl->ui32SampleRate = 1;
+       psCtrl->bInitPhaseComplete = IMG_FALSE;
+
+
+
+       psStream->psNext = 0;
+       psStream->pvBase = pvBase;
+       psStream->psCtrl = psCtrl;
+       psStream->ui32Size = ui32Size * 4096UL;
+       psStream->ui32RPtr = 0;
+       psStream->ui32WPtr = 0;
+       psStream->ui32DataWritten = 0;
+       psStream->ui32Marker = 0;
+       psStream->bCircularAllowed = IMG_TRUE;
+       psStream->ui32InitPhaseWOff = 0;
+
+
+
+       
+       if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+       {
+               pvBase = HostNonPageablePageAlloc(ui32Size);
+       }
+       else
+       {
+               pvBase = HostPageablePageAlloc(ui32Size);
+       }
+
+       if (!pvBase)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
+               
+               if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+               {
+                       HostNonPageablePageFree(psStream->pvBase);
+               }
+               else
+               {
+                       HostPageablePageFree(psStream->pvBase);
+               }
+               HostNonPageablePageFree(psStream);
+               return((IMG_VOID *) 0);
+       }
+
+       
+       psInitStream->psNext = 0;
+       psInitStream->pvBase = pvBase;
+       psInitStream->psCtrl = psCtrl;
+       psInitStream->ui32Size = ui32Size * 4096UL;
+       psInitStream->ui32RPtr = 0;
+       psInitStream->ui32WPtr = 0;
+       psInitStream->ui32DataWritten = 0;
+       psInitStream->ui32Marker = 0;
+       psInitStream->bCircularAllowed = IMG_FALSE;
+       psInitStream->ui32InitPhaseWOff = 0;
+
+
+
+       psStream->psInitStream = psInitStream;
+
+       
+       psLFBuffer->psStream = psStream;
+       psLFBuffer->ui32BufLen = 0UL;
+
+       g_bHotkeyMiddump = IMG_FALSE;
+       g_ui32HotkeyMiddumpStart = 0xffffffffUL;
+       g_ui32HotkeyMiddumpEnd = 0xffffffffUL;
+
+       
+
+       ui32Off = 0;
+
+       do
+       {
+               psStream->szName[ui32Off] = pszName[ui32Off];
+               psInitStream->szName[ui32Off] = pszName[ui32Off];
+               ui32Off++;
+       }
+       while ((pszName[ui32Off] != 0) && (ui32Off < (4096UL - sizeof(DBG_STREAM))));
+       psStream->szName[ui32Off] = pszName[ui32Off];   
+
+       
+
+       ui32OffSuffix = 0;
+       do
+       {
+               psInitStream->szName[ui32Off] = pszNameInitSuffix[ui32OffSuffix];
+               ui32Off++;
+               ui32OffSuffix++;
+       }
+       while ( (pszNameInitSuffix[ui32OffSuffix] != 0) &&
+                       (ui32Off < (4096UL - sizeof(DBG_STREAM))));
+       psInitStream->szName[ui32Off] = pszNameInitSuffix[ui32OffSuffix];       
+
+       
+
+       psStream->psNext = g_psStreamList;
+       g_psStreamList = psStream;
+
+       psLFBuffer->psNext = g_psLFBufferList;
+       g_psLFBufferList = psLFBuffer;
+
+       AddSIDEntry(psStream);
+       
+       return((IMG_VOID *) psStream);
+}
+
+void IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+       PDBG_STREAM     psStreamThis;
+       PDBG_STREAM     psStreamPrev;
+       PDBG_LASTFRAME_BUFFER   psLFBuffer;
+       PDBG_LASTFRAME_BUFFER   psLFThis;
+       PDBG_LASTFRAME_BUFFER   psLFPrev;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
+
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       RemoveSIDEntry(psStream);
+       
+       psLFBuffer = FindLFBuf(psStream);
+
+       
+
+       psStreamThis = g_psStreamList;
+       psStreamPrev = 0;
+
+       while (psStreamThis)
+       {
+               if (psStreamThis == psStream)
+               {
+                       if (psStreamPrev)
+                       {
+                               psStreamPrev->psNext = psStreamThis->psNext;
+                       }
+                       else
+                       {
+                               g_psStreamList = psStreamThis->psNext;
+                       }
+
+                       psStreamThis = 0;
+               }
+               else
+               {
+                       psStreamPrev = psStreamThis;
+                       psStreamThis = psStreamThis->psNext;
+               }
+       }
+
+       psLFThis = g_psLFBufferList;
+       psLFPrev = 0;
+
+       while (psLFThis)
+       {
+               if (psLFThis == psLFBuffer)
+               {
+                       if (psLFPrev)
+                       {
+                               psLFPrev->psNext = psLFThis->psNext;
+                       }
+                       else
+                       {
+                               g_psLFBufferList = psLFThis->psNext;
+                       }
+
+                       psLFThis = 0;
+               }
+               else
+               {
+                       psLFPrev = psLFThis;
+                       psLFThis = psLFThis->psNext;
+               }
+       }
+       
+
+       if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+       {
+               DeactivateHotKeys();
+       }
+
+       
+
+       if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+       {
+               HostNonPageablePageFree(psStream->psCtrl);
+               HostNonPageablePageFree(psStream->pvBase);
+               HostNonPageablePageFree(psStream->psInitStream->pvBase);
+       }
+       else
+       {
+               HostNonPageablePageFree(psStream->psCtrl);
+               HostPageablePageFree(psStream->pvBase);
+               HostPageablePageFree(psStream->psInitStream->pvBase);
+       }
+       
+       HostNonPageablePageFree(psStream->psInitStream);
+       HostNonPageablePageFree(psStream);
+       HostNonPageablePageFree(psLFBuffer);
+
+       if (g_psStreamList == 0)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
+       }
+
+       return;
+}
+
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+       PDBG_STREAM     psStream;
+       PDBG_STREAM     psThis;
+       IMG_UINT32      ui32Off;
+       IMG_BOOL        bAreSame;
+
+       psStream = 0;
+
+       PVR_DPF((PVR_DBGDRIV_MESSAGE, "PDump client connecting to %s %s",
+                       pszName,
+                       (bResetStream == IMG_TRUE) ? "with reset" : "no reset"));
+
+       
+
+       for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
+       {
+               bAreSame = IMG_TRUE;
+               ui32Off = 0;
+
+               if (strlen(psThis->szName) == strlen(pszName))
+               {
+                       while ((psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && (ui32Off < 128) && bAreSame)
+                       {
+                               if (psThis->szName[ui32Off] != pszName[ui32Off])
+                               {
+                                       bAreSame = IMG_FALSE;
+                               }
+
+                               ui32Off++;
+                       }
+               }
+               else
+               {
+                       bAreSame = IMG_FALSE;
+               }
+
+               if (bAreSame)
+               {
+                       psStream = psThis;
+                       break;
+               }
+       }
+
+       if(bResetStream && psStream)
+       {
+               static IMG_CHAR szComment[] = "-- Init phase terminated\r\n";
+               psStream->psInitStream->ui32RPtr = 0;
+               psStream->ui32RPtr = 0;
+               psStream->ui32WPtr = 0;
+               psStream->ui32DataWritten = psStream->psInitStream->ui32DataWritten;
+               if (psStream->psCtrl->bInitPhaseComplete == IMG_FALSE)
+               {
+                       if (psStream->psCtrl->ui32Flags & DEBUG_FLAGS_TEXTSTREAM)
+                       {
+                               DBGDrivWrite2(psStream, (IMG_UINT8 *)szComment, sizeof(szComment) - 1, 0x01);
+                       }
+                       psStream->psCtrl->bInitPhaseComplete = IMG_TRUE;
+               }
+
+               {
+                       
+                       
+                       psStream->psInitStream->ui32InitPhaseWOff = psStream->psInitStream->ui32WPtr;
+                       PVR_DPF((PVR_DBGDRIV_MESSAGE, "Set %s client marker bo %x, total bw %x",
+                                       psStream->szName,
+                                       psStream->psInitStream->ui32InitPhaseWOff,
+                                       psStream->psInitStream->ui32DataWritten ));
+               }
+       }
+
+       return((IMG_VOID *) psStream);
+}
+
+static void IMG_CALLCONV DBGDrivInvalidateStream(PDBG_STREAM psStream)
+{
+       IMG_CHAR pszErrorMsg[] = "**OUTOFMEM\n";
+       IMG_UINT32 ui32Space;
+       IMG_UINT32 ui32Off = 0;
+       IMG_UINT32 ui32WPtr = psStream->ui32WPtr;
+       IMG_PUINT8 pui8Buffer = (IMG_UINT8 *) psStream->pvBase;
+
+       PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: An error occurred for stream %s\r\n", psStream->szName ));
+
+
+
+
+
+
+
+
+
+       ui32Space = SpaceInStream(psStream);
+
+
+       if(ui32Space > 0)
+       {
+               ui32Space--;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: Buffer full."));
+       }
+
+       while((pszErrorMsg[ui32Off] != 0) && (ui32Off < ui32Space))
+       {
+               pui8Buffer[ui32WPtr] = (IMG_UINT8)pszErrorMsg[ui32Off];
+               ui32Off++;
+               ui32WPtr++;
+       }
+       pui8Buffer[ui32WPtr++] = '\0';
+       psStream->ui32WPtr = ui32WPtr;
+
+
+       psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_READONLY;
+}
+
+static IMG_VOID InvalidateAllStreams(IMG_VOID)
+{
+       PDBG_STREAM psStream = g_psStreamList;
+       while (psStream != IMG_NULL)
+       {
+               DBGDrivInvalidateStream(psStream);
+               psStream = psStream->psNext;
+       }
+       return;
+}
+
+
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+       
+
+       if (!StreamValidForWrite(psStream))
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+       {
+               if      ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+               {
+                       return(0);
+               }
+       }
+       else
+       {
+               if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+               {
+                       if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+                       {
+                               return(0);
+                       }
+               }
+       }
+
+       return(DBGDrivWriteString(psStream,pszString,ui32Level));
+
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+       IMG_UINT32      ui32Len;
+       IMG_UINT32      ui32Space;
+       IMG_UINT32      ui32WPtr;
+       IMG_UINT8 *     pui8Buffer;
+
+       
+
+       if (!StreamValidForWrite(psStream))
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       if ((psStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+
+       if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_ASYNC) == 0)
+       {
+               if (psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STANDARDDBG)
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,"%s: %s\r\n",psStream->szName, pszString));
+               }
+
+               
+
+               if (psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_MONO)
+               {
+                       MonoOut(psStream->szName,IMG_FALSE);
+                       MonoOut(": ",IMG_FALSE);
+                       MonoOut(pszString,IMG_TRUE);
+               }
+       }
+
+       
+
+       if      (
+                       !(
+                               ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) != 0) ||
+                               ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_ASYNC) != 0)
+                       )
+               )
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       ui32Space=SpaceInStream(psStream);
+
+       
+       if(ui32Space > 0)
+       {
+               ui32Space--;
+       }
+
+       ui32Len         = 0;
+       ui32WPtr        = psStream->ui32WPtr;
+       pui8Buffer      = (IMG_UINT8 *) psStream->pvBase;
+
+       while((pszString[ui32Len] != 0) && (ui32Len < ui32Space))
+       {
+               pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+               ui32Len++;
+               ui32WPtr++;
+               if (ui32WPtr == psStream->ui32Size)
+               {
+                       ui32WPtr = 0;
+               }
+       }
+
+       if (ui32Len < ui32Space)
+       {
+               
+               pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+               ui32Len++;
+               ui32WPtr++;
+               if (ui32WPtr == psStream->ui32Size)
+               {
+                       ui32WPtr = 0;
+               }
+
+               
+               psStream->ui32WPtr = ui32WPtr;
+               psStream->ui32DataWritten+= ui32Len;
+       } else
+       {
+               ui32Len = 0;
+       }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+       if (ui32Len)
+       {
+               HostSignalEvent(DBG_EVENT_STREAM_DATA);
+       }
+#endif
+
+       return(ui32Len);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+       IMG_UINT32                              ui32OutLen;
+       IMG_UINT32                              ui32Len;
+       IMG_UINT32                              ui32Offset;
+       IMG_UINT8                               *pui8Buff;
+
+       
+
+       if (!StreamValidForRead(psStream))
+       {
+               return(0);
+       }
+
+       
+
+       pui8Buff = (IMG_UINT8 *)psStream->pvBase;
+       ui32Offset = psStream->ui32RPtr;
+
+       if (psStream->ui32RPtr == psStream->ui32WPtr)
+       {
+               return(0);
+       }
+
+       
+
+       ui32Len = 0;
+       while((pui8Buff[ui32Offset] != 0) && (ui32Offset != psStream->ui32WPtr))
+       {
+               ui32Offset++;
+               ui32Len++;
+
+               
+
+               if (ui32Offset == psStream->ui32Size)
+               {
+                       ui32Offset = 0;
+               }
+       }
+
+       ui32OutLen = ui32Len + 1;
+
+       
+
+       if (ui32Len > ui32Limit)
+       {
+               return(0);
+       }
+
+       
+
+       ui32Offset = psStream->ui32RPtr;
+       ui32Len = 0;
+
+       while ((pui8Buff[ui32Offset] != 0) && (ui32Len < ui32Limit))
+       {
+               pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+               ui32Offset++;
+               ui32Len++;
+
+               
+
+               if (ui32Offset == psStream->ui32Size)
+               {
+                       ui32Offset = 0;
+               }
+       }
+
+       pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+
+       psStream->ui32RPtr = ui32Offset + 1;
+
+       if (psStream->ui32RPtr == psStream->ui32Size)
+       {
+               psStream->ui32RPtr = 0;
+       }
+
+       return(ui32OutLen);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+       IMG_UINT32                              ui32Space;
+       DBG_STREAM *psStream;
+
+       
+
+       if (!StreamValidForWrite(psMainStream))
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       if ((psMainStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       if (psMainStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+       {
+               if      ((psMainStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+               {
+
+                       return(ui32InBuffSize);
+               }
+       }
+       else if (psMainStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+       {
+               if ((psMainStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+               {
+
+                       return(ui32InBuffSize);
+               }
+       }
+
+       if(psMainStream->psCtrl->bInitPhaseComplete)
+       {
+               psStream = psMainStream;
+       }
+       else
+       {
+               psStream = psMainStream->psInitStream;
+       }
+
+       
+
+       ui32Space=SpaceInStream(psStream);
+
+       PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv %d b for %s: Roff = %x, WOff = %x",
+                       ui32InBuffSize,
+                       psStream->szName,
+                       psStream->ui32RPtr,
+                       psStream->ui32WPtr));
+
+       
+
+       if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite: buffer %x is disabled", (IMG_UINTPTR_T) psStream));
+               return(0);
+       }
+
+       if (ui32Space < 8)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite: buffer %x is full", (IMG_UINTPTR_T) psStream));
+               return(0);
+       }
+
+       
+
+       if (ui32Space <= (ui32InBuffSize + 4))
+       {
+               ui32InBuffSize = ui32Space - 8;
+       }
+
+       
+
+       Write(psStream,(IMG_UINT8 *) &ui32InBuffSize,4);
+       Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+       if (ui32InBuffSize)
+       {
+               HostSignalEvent(DBG_EVENT_STREAM_DATA);
+       }
+#endif
+       return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+       
+
+       if (!StreamValidForWrite(psStream))
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+       {
+               if      ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+               {
+
+                       return(ui32InBuffSize);
+               }
+       }
+       else
+       {
+               if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+               {
+                       if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+                       {
+
+                               return(ui32InBuffSize);
+                       }
+               }
+       }
+
+       return(DBGDrivWrite2(psStream,pui8InBuf,ui32InBuffSize,ui32Level));
+}
+
+
+static IMG_UINT32 DBGDrivWritePersist(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+       DBG_STREAM      *psStream;
+       PVR_UNREFERENCED_PARAMETER(ui32Level);
+
+       
+
+       if (!StreamValidForWrite(psMainStream))
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+       psStream = psMainStream->psInitStream;
+       if(psStream->bCircularAllowed == IMG_TRUE)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "DBGDrivWritePersist: Init phase is a circular buffer, some data may be lost"));
+       }
+
+       PVR_DPF((PVR_DBGDRIV_MESSAGE, "Append %x b to %s: Roff = %x, WOff = %x [bw = %x]",
+                       ui32InBuffSize,
+                       psStream->szName,
+                       psStream->ui32RPtr,
+                       psStream->ui32WPtr,
+                       psStream->ui32DataWritten));
+
+       return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
+       }
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+       {
+       DBG_STREAM      *psStream;
+
+       
+
+       if (!StreamValidForWrite(psMainStream))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite2: stream not valid"));
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       if ((psMainStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+       {
+               return(0);
+       }
+
+       if(psMainStream->psCtrl->bInitPhaseComplete)
+       {
+               psStream = psMainStream;
+       }
+       else
+       {
+               psStream = psMainStream->psInitStream;
+       }
+
+       PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv(exp) %d b for %s: Roff = %x, WOff = %x",
+                       ui32InBuffSize,
+                       psStream->szName,
+                       psStream->ui32RPtr,
+                       psStream->ui32WPtr));
+
+       return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+       IMG_UINT32 ui32Data;
+       DBG_STREAM *psStream;
+
+       
+
+       if (!StreamValidForRead(psMainStream))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "DBGDrivRead: buffer %x is invalid", (IMG_UINTPTR_T) psMainStream));
+               return(0);
+       }
+
+       if(bReadInitBuffer)
+       {
+               psStream = psMainStream->psInitStream;
+       }
+       else
+       {
+               psStream = psMainStream;
+       }
+
+       
+       if (psStream->ui32RPtr == psStream->ui32WPtr ||
+               ((psStream->ui32InitPhaseWOff > 0) &&
+                (psStream->ui32RPtr >= psStream->ui32InitPhaseWOff)) )
+       {
+               return(0);
+       }
+
+       
+
+       if (psStream->ui32RPtr <= psStream->ui32WPtr)
+       {
+               ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
+       }
+       else
+       {
+               ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
+       }
+
+       
+
+       if ((psStream->ui32InitPhaseWOff > 0) &&
+               (psStream->ui32InitPhaseWOff < psStream->ui32WPtr))
+       {
+               ui32Data = psStream->ui32InitPhaseWOff - psStream->ui32RPtr;
+       }
+
+       
+
+       if (ui32Data > ui32OutBuffSize)
+       {
+               ui32Data = ui32OutBuffSize;
+       }
+
+       PVR_DPF((PVR_DBGDRIV_MESSAGE, "Send %x b from %s: Roff = %x, WOff = %x",
+                       ui32Data,
+                       psStream->szName,
+                       psStream->ui32RPtr,
+                       psStream->ui32WPtr));
+
+       
+
+       if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
+       {       
+               IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
+               IMG_UINT32 ui32B2 = ui32Data - ui32B1;
+
+               
+               HostMemCopy((IMG_VOID *) pui8OutBuf,
+                               (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+                               ui32B1);
+
+               
+               HostMemCopy((IMG_VOID *)(pui8OutBuf + ui32B1),
+                               psStream->pvBase,
+                               ui32B2);
+
+               
+               psStream->ui32RPtr = ui32B2;
+       }
+       else
+       {       
+               HostMemCopy((IMG_VOID *) pui8OutBuf,
+                               (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+                               ui32Data);
+
+               
+               psStream->ui32RPtr += ui32Data;
+
+               
+               if (psStream->ui32RPtr == psStream->ui32Size)
+               {
+                       psStream->ui32RPtr = 0;
+               }
+       }
+
+       return(ui32Data);
+}
+
+void IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       psStream->psCtrl->ui32CapMode = ui32Mode;
+       psStream->psCtrl->ui32DefaultMode = ui32Mode;
+       psStream->psCtrl->ui32Start = ui32Start;
+       psStream->psCtrl->ui32End = ui32End;
+       psStream->psCtrl->ui32SampleRate = ui32SampleRate;
+
+       
+
+       if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+       {
+               ActivateHotKeys(psStream);
+       }
+}
+
+void IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       psStream->psCtrl->ui32OutMode = ui32OutMode;
+}
+
+void IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       psStream->psCtrl->ui32DebugLevel = ui32DebugLevel;
+}
+
+void IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       psStream->psCtrl->ui32Current = ui32Frame;
+
+       if ((ui32Frame >= psStream->psCtrl->ui32Start) &&
+               (ui32Frame <= psStream->psCtrl->ui32End) &&
+               (((ui32Frame - psStream->psCtrl->ui32Start) % psStream->psCtrl->ui32SampleRate) == 0))
+       {
+               psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+       }
+       else
+       {
+               psStream->psCtrl->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+       }
+
+       if (g_bHotkeyMiddump)
+       {
+               if ((ui32Frame >= g_ui32HotkeyMiddumpStart) &&
+                       (ui32Frame <= g_ui32HotkeyMiddumpEnd) &&
+                       (((ui32Frame - g_ui32HotkeyMiddumpStart) % psStream->psCtrl->ui32SampleRate) == 0))
+               {
+                       psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+               }
+               else
+               {
+                       psStream->psCtrl->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+                       if (psStream->psCtrl->ui32Current > g_ui32HotkeyMiddumpEnd)
+                       {
+                               g_bHotkeyMiddump = IMG_FALSE;
+                       }
+               }
+       }
+
+       
+       if (g_bHotKeyRegistered)
+       {
+               g_bHotKeyRegistered = IMG_FALSE;
+
+               PVR_DPF((PVR_DBG_MESSAGE,"Hotkey pressed (%p)!\n",psStream));
+
+               if (!g_bHotKeyPressed)
+               {
+                       
+
+                       g_ui32HotKeyFrame = psStream->psCtrl->ui32Current + 2;
+
+                       
+
+                       g_bHotKeyPressed = IMG_TRUE;
+               }
+
+               
+
+               if (((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+                       ((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY) != 0))
+               {
+                       if (!g_bHotkeyMiddump)
+                       {
+                               
+                               g_ui32HotkeyMiddumpStart = g_ui32HotKeyFrame + 1;
+                               g_ui32HotkeyMiddumpEnd = 0xffffffff;
+                               g_bHotkeyMiddump = IMG_TRUE;
+                               PVR_DPF((PVR_DBG_MESSAGE,"Sampling every %d frame(s)\n", psStream->psCtrl->ui32SampleRate));
+                       }
+                       else
+                       {
+                               
+                               g_ui32HotkeyMiddumpEnd = g_ui32HotKeyFrame;
+                               PVR_DPF((PVR_DBG_MESSAGE,"Turning off sampling\n"));
+                       }
+               }
+
+       }
+
+       
+
+       if (psStream->psCtrl->ui32Current > g_ui32HotKeyFrame)
+       {
+               g_bHotKeyPressed = IMG_FALSE;
+       }
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return(0);
+       }
+
+       return(psStream->psCtrl->ui32Current);
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+       IMG_UINT32      ui32NextFrame;
+
+       
+
+       if (!StreamValid(psStream))
+       {
+               return IMG_FALSE;
+       }
+
+       if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+       {
+               ui32NextFrame = psStream->psCtrl->ui32Current + psStream->psCtrl->ui32SampleRate;
+               if (ui32NextFrame > psStream->psCtrl->ui32End)
+               {
+                       return IMG_TRUE;
+               }
+       }
+       return IMG_FALSE;
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+       IMG_UINT32 ui32FrameShift = bCheckPreviousFrame ? 1UL : 0UL;
+
+       
+
+       if (!StreamValid(psStream))
+       {
+               return IMG_FALSE;
+       }
+
+       if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+       {
+               
+               if (g_bHotkeyMiddump)
+               {
+                       if ((psStream->psCtrl->ui32Current >= (g_ui32HotkeyMiddumpStart - ui32FrameShift)) &&
+                               (psStream->psCtrl->ui32Current <= (g_ui32HotkeyMiddumpEnd - ui32FrameShift)) &&
+                               ((((psStream->psCtrl->ui32Current + ui32FrameShift) - g_ui32HotkeyMiddumpStart) % psStream->psCtrl->ui32SampleRate) == 0))
+                       {
+                               return IMG_TRUE;
+                       }
+               }
+               else
+               {
+                       if ((psStream->psCtrl->ui32Current >= (psStream->psCtrl->ui32Start - ui32FrameShift)) &&
+                               (psStream->psCtrl->ui32Current <= (psStream->psCtrl->ui32End - ui32FrameShift)) &&
+                               ((((psStream->psCtrl->ui32Current + ui32FrameShift) - psStream->psCtrl->ui32Start) % psStream->psCtrl->ui32SampleRate) == 0))
+                       {
+                               return IMG_TRUE;
+                       }
+               }
+       }
+       else if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+       {
+               if ((psStream->psCtrl->ui32Current == (g_ui32HotKeyFrame-ui32FrameShift)) && (g_bHotKeyPressed))
+               {
+                       return IMG_TRUE;
+               }
+       }
+       return IMG_FALSE;
+}
+
+void IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       psStream->psCtrl->ui32CapMode = ui32Mode;
+}
+
+void IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       psStream->psCtrl->ui32CapMode = psStream->psCtrl->ui32DefaultMode;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetClientMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       psStream->ui32InitPhaseWOff = ui32Marker;
+}
+
+void IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return;
+       }
+
+       psStream->ui32Marker = ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
+{
+       
+
+       if (!StreamValid(psStream))
+       {
+               return 0;
+       }
+
+       return psStream->ui32Marker;
+}
+
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psMainStream)
+{
+       PDBG_STREAM psStream;
+
+       
+
+       if (!StreamValid(psMainStream))
+       {
+               return 0;
+       }
+
+       if(psMainStream->psCtrl->bInitPhaseComplete)
+       {
+               psStream = psMainStream;
+       }
+       else
+       {
+               psStream = psMainStream->psInitStream;
+       }
+
+       return psStream->ui32DataWritten;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psMainStream, IMG_UINT32 ui32StreamOffset)
+{
+       PDBG_STREAM psStream;
+
+       
+
+       if (!StreamValid(psMainStream))
+       {
+               return;
+       }
+
+       if(psMainStream->psCtrl->bInitPhaseComplete)
+       {
+               psStream = psMainStream;
+       }
+       else
+       {
+               psStream = psMainStream->psInitStream;
+       }
+
+       PVR_DPF((PVR_DBGDRIV_MESSAGE, "DBGDrivSetStreamOffset: %s set to %x b",
+                       psStream->szName,
+                       ui32StreamOffset));
+       psStream->ui32DataWritten = ui32StreamOffset;
+}
+
+IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID)
+{
+       return((IMG_PVOID)&g_sDBGKMServices);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+       PDBG_LASTFRAME_BUFFER   psLFBuffer;
+
+       
+
+       if (!StreamValidForWrite(psStream))
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       if ((psStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+       {
+               return(0xFFFFFFFFUL);
+       }
+
+       
+
+       if ((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0)
+       {
+               if      ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+               {
+
+                       return(ui32InBuffSize);
+               }
+       }
+       else if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+       {
+               if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+               {
+
+                       return(ui32InBuffSize);
+               }
+       }
+
+       psLFBuffer = FindLFBuf(psStream);
+
+       if (ui32Flags & WRITELF_FLAGS_RESETBUF)
+       {
+               
+
+               ui32InBuffSize = (ui32InBuffSize > LAST_FRAME_BUF_SIZE) ? LAST_FRAME_BUF_SIZE : ui32InBuffSize;
+               HostMemCopy((IMG_VOID *)psLFBuffer->ui8Buffer, (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+               psLFBuffer->ui32BufLen = ui32InBuffSize;
+       }
+       else
+       {
+               
+
+               ui32InBuffSize = ((psLFBuffer->ui32BufLen + ui32InBuffSize) > LAST_FRAME_BUF_SIZE) ? (LAST_FRAME_BUF_SIZE - psLFBuffer->ui32BufLen) : ui32InBuffSize;
+               HostMemCopy((IMG_VOID *)(&psLFBuffer->ui8Buffer[psLFBuffer->ui32BufLen]), (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+               psLFBuffer->ui32BufLen += ui32InBuffSize;
+       }
+
+       return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+       PDBG_LASTFRAME_BUFFER   psLFBuffer;
+       IMG_UINT32      ui32Data;
+
+       
+
+       if (!StreamValidForRead(psStream))
+       {
+               return(0);
+       }
+
+       psLFBuffer = FindLFBuf(psStream);
+
+       
+
+       ui32Data = (ui32OutBuffSize < psLFBuffer->ui32BufLen) ? ui32OutBuffSize : psLFBuffer->ui32BufLen;
+
+       
+
+       HostMemCopy((IMG_VOID *)pui8OutBuf, (IMG_VOID *)psLFBuffer->ui8Buffer, ui32Data);
+
+       return ui32Data;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+       psStream->psCtrl->bInitPhaseComplete = IMG_FALSE;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+       psStream->psCtrl->bInitPhaseComplete = IMG_TRUE;
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+       HostWaitForEvent(eEvent);
+}
+#endif
+
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
+{
+       IMG_VOID *      pvNewBuf;
+       IMG_UINT32      ui32NewSizeInPages;
+       IMG_UINT32      ui32NewWOffset;
+       IMG_UINT32      ui32NewROffset;
+       IMG_UINT32      ui32SpaceInOldBuf;
+
+       
+
+       if (psStream->ui32Size >= ui32NewSize)
+       {
+               return IMG_FALSE;
+       }
+
+       
+
+       ui32SpaceInOldBuf = SpaceInStream(psStream);
+
+       
+
+       ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
+
+       if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+       {
+               pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
+       }
+       else
+       {
+               pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
+       }
+
+       if (pvNewBuf == IMG_NULL)
+       {
+               return IMG_FALSE;
+       }
+
+       if(psStream->bCircularAllowed)
+       {
+               
+
+
+               if (psStream->ui32RPtr <= psStream->ui32WPtr)
+               {
+                       
+
+               HostMemCopy(pvNewBuf,
+                                       (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+                                       psStream->ui32WPtr - psStream->ui32RPtr);
+               }
+               else
+               {
+                       IMG_UINT32      ui32FirstCopySize;
+       
+                       
+
+                       ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
+       
+                       HostMemCopy(pvNewBuf,
+                                       (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+                                       ui32FirstCopySize);
+       
+                       
+
+                       HostMemCopy((IMG_VOID *)((IMG_UINTPTR_T)pvNewBuf + ui32FirstCopySize),
+                                       (IMG_VOID *)(IMG_PBYTE)psStream->pvBase,
+                                       psStream->ui32WPtr);
+               }
+               ui32NewROffset = 0;
+       }
+       else
+       {
+               
+               HostMemCopy(pvNewBuf, psStream->pvBase, psStream->ui32WPtr);
+               ui32NewROffset = psStream->ui32RPtr;
+       }
+
+       
+
+                                                        
+       ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
+
+       
+
+       if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+       {
+               HostNonPageablePageFree(psStream->pvBase);
+       }
+       else
+       {
+               HostPageablePageFree(psStream->pvBase);
+       }
+
+       
+
+       psStream->pvBase = pvNewBuf;
+       psStream->ui32RPtr = ui32NewROffset;
+       psStream->ui32WPtr = ui32NewWOffset;
+       psStream->ui32Size = ui32NewSizeInPages * 4096;
+
+       return IMG_TRUE;
+}
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
+{
+       IMG_UINT32      ui32Space;
+
+       if (psStream->bCircularAllowed)
+       {
+               
+       if (psStream->ui32RPtr > psStream->ui32WPtr)
+       {
+               ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
+       }
+       else
+       {
+               ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
+       }
+       }
+       else
+       {
+               
+               ui32Space = psStream->ui32Size - psStream->ui32WPtr;
+       }
+
+       return ui32Space;
+}
+
+
+void DestroyAllStreams(void)
+{
+       while (g_psStreamList != IMG_NULL)
+       {
+               DBGDrivDestroyStream(g_psStreamList);
+       }
+       return;
+}
+
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream)
+{
+       PDBG_LASTFRAME_BUFFER   psLFBuffer;
+
+       psLFBuffer = g_psLFBufferList;
+
+       while (psLFBuffer)
+       {
+               if (psLFBuffer->psStream == psStream)
+               {
+                       break;
+               }
+
+               psLFBuffer = psLFBuffer->psNext;
+       }
+
+       return psLFBuffer;
+}
+
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h
new file mode 100644 (file)
index 0000000..52caa06
--- /dev/null
@@ -0,0 +1,122 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _DBGDRIV_
+#define _DBGDRIV_
+
+#define BUFFER_SIZE 64*PAGESIZE
+
+#define DBGDRIV_VERSION        0x100
+#define MAX_PROCESSES          2
+#define BLOCK_USED                     0x01
+#define BLOCK_LOCKED           0x02
+#define DBGDRIV_MONOBASE       0x000B0000
+
+
+extern IMG_VOID *      g_pvAPIMutex;
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *         pszName,
+                                                                  IMG_UINT32   ui32CapMode,
+                                                                  IMG_UINT32   ui32OutMode,
+                                                                  IMG_UINT32   ui32Flags,
+                                                                  IMG_UINT32   ui32Pages);
+IMG_VOID   IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID   IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+IMG_VOID   IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID   IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID   IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID   IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_PVOID  IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID   IMG_CALLCONV DBGDrivSetClientMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_VOID   IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_BOOL   IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL   IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_VOID   IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID   IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent);
+
+IMG_VOID DestroyAllStreams(IMG_VOID);
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn);
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest,IMG_UINT8 ui8Value,IMG_UINT32 ui32Size);
+IMG_VOID HostMemCopy(IMG_VOID *pvDest,IMG_VOID *pvSrc,IMG_UINT32 ui32Size);
+IMG_VOID MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine);
+
+IMG_SID PStream2SID(PDBG_STREAM psStream);
+PDBG_STREAM SID2PStream(IMG_SID hStream); 
+IMG_BOOL AddSIDEntry(PDBG_STREAM psStream);
+IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream);
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *      pszName, IMG_UINT32 ui32CapMode, IMG_UINT32     ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_BOOL   IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL   IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetConnectNotifier(DBGKM_CONNECT_NOTIFIER fn_notifier);
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWritePersist(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv_ioctl.h b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/dbgdriv_ioctl.h
new file mode 100644 (file)
index 0000000..fef576e
--- /dev/null
@@ -0,0 +1,34 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _IOCTL_
+#define _IOCTL_
+
+#define MAX_DBGVXD_W32_API 25
+
+extern IMG_UINT32 (*g_DBGDrivProc[MAX_DBGVXD_W32_API])(IMG_VOID *, IMG_VOID *);
+
+#endif
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/handle.c b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/handle.c
new file mode 100644 (file)
index 0000000..59d920b
--- /dev/null
@@ -0,0 +1,121 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+
+#define MAX_SID_ENTRIES                8
+
+typedef struct _SID_INFO
+{
+       PDBG_STREAM     psStream;
+} SID_INFO, *PSID_INFO;
+
+static SID_INFO gaSID_Xlat_Table[MAX_SID_ENTRIES];
+
+IMG_SID PStream2SID(PDBG_STREAM psStream)
+{
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               IMG_INT32 iIdx;
+
+               for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+               {
+                       if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+                       {
+                               
+                               return (IMG_SID)iIdx+1;
+                       }
+               }
+       }
+
+       return (IMG_SID)0;
+}
+
+
+PDBG_STREAM SID2PStream(IMG_SID hStream)
+{
+       
+       IMG_INT32 iIdx = (IMG_INT32)hStream-1;
+
+       if (iIdx >= 0 && iIdx < MAX_SID_ENTRIES)
+       {
+               return gaSID_Xlat_Table[iIdx].psStream;
+       }
+       else
+       {
+       return (PDBG_STREAM)IMG_NULL;
+    }
+}
+
+
+IMG_BOOL AddSIDEntry(PDBG_STREAM psStream)
+{
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               IMG_INT32 iIdx;
+
+               for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+               {
+                       if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+                       {
+                               
+                               return IMG_TRUE;
+                       }
+
+                       if (gaSID_Xlat_Table[iIdx].psStream == (PDBG_STREAM)IMG_NULL)
+                       {
+                               
+                               gaSID_Xlat_Table[iIdx].psStream = psStream;
+                               return IMG_TRUE;
+                       }
+               }
+       }
+
+       return IMG_FALSE;
+}
+
+IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream)
+{
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               IMG_INT32 iIdx;
+
+               for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+               {
+                       if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+                       {
+                               gaSID_Xlat_Table[iIdx].psStream = (PDBG_STREAM)IMG_NULL;
+                               return IMG_TRUE;
+                       }
+               }
+       }
+
+       return IMG_FALSE;
+}
+
+
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h
new file mode 100644 (file)
index 0000000..3a29db6
--- /dev/null
@@ -0,0 +1,58 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#ifndef _HOSTFUNC_
+#define _HOSTFUNC_
+
+#define HOST_PAGESIZE                  (4096)
+#define DBG_MEMORY_INITIALIZER (0xe2)
+
+IMG_UINT32 HostReadRegistryDWORDFromString(IMG_CHAR *pcKey, IMG_CHAR *pcValueName, IMG_UINT32 *pui32Data);
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase);
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase);
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID * *ppvMdl);
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess);
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID);
+
+IMG_VOID * HostCreateMutex(IMG_VOID);
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex);
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex);
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_INT32 HostCreateEventObjects(IMG_VOID);
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent);
+IMG_VOID HostDestroyEventObjects(IMG_VOID);
+#endif 
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hotkey.c b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hotkey.c
new file mode 100644 (file)
index 0000000..48853c7
--- /dev/null
@@ -0,0 +1,135 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+#if !defined(LINUX)
+#include <ntddk.h>
+#include <windef.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+
+
+
+
+IMG_UINT32     g_ui32HotKeyFrame = 0xFFFFFFFF;
+IMG_BOOL       g_bHotKeyPressed = IMG_FALSE;
+IMG_BOOL       g_bHotKeyRegistered = IMG_FALSE;
+
+PRIVATEHOTKEYDATA    g_PrivateHotKeyData;
+
+
+IMG_VOID ReadInHotKeys(IMG_VOID)
+{
+       g_PrivateHotKeyData.ui32ScanCode = 0x58;
+       g_PrivateHotKeyData.ui32ShiftState = 0x0;
+
+
+
+#if 0
+       if (_RegOpenKey(HKEY_LOCAL_MACHINE,pszRegPath,&hKey) == ERROR_SUCCESS)
+       {
+
+
+               QueryReg(hKey,"ui32ScanCode",&g_PrivateHotKeyData.ui32ScanCode);
+               QueryReg(hKey,"ui32ShiftState",&g_PrivateHotKeyData.ui32ShiftState);
+       }
+#else
+       HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ScanCode"  , &g_PrivateHotKeyData.ui32ScanCode);
+       HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ShiftState", &g_PrivateHotKeyData.ui32ShiftState);
+#endif
+}
+
+IMG_VOID RegisterKeyPressed(IMG_UINT32 dwui32ScanCode, PHOTKEYINFO pInfo)
+{
+       PDBG_STREAM     psStream;
+
+       PVR_UNREFERENCED_PARAMETER(pInfo);
+
+       if (dwui32ScanCode == g_PrivateHotKeyData.ui32ScanCode)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE,"PDUMP Hotkey pressed !\n"));
+
+               psStream = (PDBG_STREAM) g_PrivateHotKeyData.sHotKeyInfo.pvStream;
+
+               if (!g_bHotKeyPressed)
+               {
+
+
+                       g_ui32HotKeyFrame = psStream->psCtrl->ui32Current + 2;
+
+
+
+                       g_bHotKeyPressed = IMG_TRUE;
+               }
+       }
+}
+
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream)
+{
+
+
+       ReadInHotKeys();
+
+
+
+       if (!g_PrivateHotKeyData.sHotKeyInfo.hHotKey)
+       {
+               if (g_PrivateHotKeyData.ui32ScanCode != 0)
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,"Activate HotKey for PDUMP.\n"));
+
+
+
+                       g_PrivateHotKeyData.sHotKeyInfo.pvStream = psStream;
+
+                       DefineHotKey(g_PrivateHotKeyData.ui32ScanCode, g_PrivateHotKeyData.ui32ShiftState, &g_PrivateHotKeyData.sHotKeyInfo);
+               }
+               else
+               {
+                       g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+               }
+       }
+}
+
+IMG_VOID DeactivateHotKeys(IMG_VOID)
+{
+       if (g_PrivateHotKeyData.sHotKeyInfo.hHotKey != 0)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE,"Deactivate HotKey.\n"));
+
+               RemoveHotKey(g_PrivateHotKeyData.sHotKeyInfo.hHotKey);
+               g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+       }
+}
+
+
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hotkey.h b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/hotkey.h
new file mode 100644 (file)
index 0000000..d9c9458
--- /dev/null
@@ -0,0 +1,60 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _HOTKEY_
+#define _HOTKEY_
+
+
+typedef struct _hotkeyinfo
+{
+       IMG_UINT8 ui8ScanCode;
+       IMG_UINT8 ui8Type;
+       IMG_UINT8 ui8Flag;
+       IMG_UINT8 ui8Filler1;
+       IMG_UINT32 ui32ShiftState;
+       IMG_UINT32 ui32HotKeyProc;
+       IMG_VOID *pvStream;
+       IMG_UINT32 hHotKey;
+} HOTKEYINFO, *PHOTKEYINFO;
+
+typedef struct _privatehotkeydata
+{
+       IMG_UINT32              ui32ScanCode;
+       IMG_UINT32              ui32ShiftState;
+       HOTKEYINFO      sHotKeyInfo;
+} PRIVATEHOTKEYDATA, *PPRIVATEHOTKEYDATA;
+
+
+IMG_VOID ReadInHotKeys (IMG_VOID);
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream);
+IMG_VOID DeactivateHotKeys(IMG_VOID);
+
+IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey);
+IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo);
+IMG_VOID RegisterKeyPressed (IMG_UINT32 ui32ScanCode, PHOTKEYINFO psInfo);
+
+#endif
+
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/ioctl.c b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/common/ioctl.c
new file mode 100644 (file)
index 0000000..914f666
--- /dev/null
@@ -0,0 +1,586 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+
+
+#ifdef LINUX
+#include <asm/uaccess.h>
+#endif 
+
+#include "img_types.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "dbgdriv_ioctl.h"
+
+
+static IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_CREATESTREAM psIn;
+       IMG_VOID * *ppvOut;
+       #ifdef LINUX
+       static IMG_CHAR name[32];
+       #endif
+
+       psIn = (PDBG_IN_CREATESTREAM) pvInBuffer;
+       ppvOut = (IMG_VOID * *) pvOutBuffer;
+
+       #ifdef LINUX
+
+       if(copy_from_user(name, psIn->u.pszName, 32) != 0)
+       {
+               return IMG_FALSE;
+       }
+
+       *ppvOut = ExtDBGDrivCreateStream(name, psIn->ui32CapMode, psIn->ui32OutMode, 0, psIn->ui32Pages);
+
+       #else
+       *ppvOut = ExtDBGDrivCreateStream(psIn->u.pszName, psIn->ui32CapMode, psIn->ui32OutMode, DEBUG_FLAGS_NO_BUF_EXPANDSION, psIn->ui32Pages);
+       #endif
+
+
+       return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_STREAM *ppsStream;
+       PDBG_STREAM  psStream;
+
+       ppsStream = (PDBG_STREAM *) pvInBuffer;
+       psStream  = (PDBG_STREAM) *ppsStream;
+
+       PVR_UNREFERENCED_PARAMETER(     pvOutBuffer);
+
+       ExtDBGDrivDestroyStream(psStream);
+
+       return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_FINDSTREAM psParams;
+       IMG_SID *       phStream;
+
+       psParams        = (PDBG_IN_FINDSTREAM)pvInBuffer;
+       phStream        = (IMG_SID *)pvOutBuffer;
+
+       *phStream = PStream2SID(ExtDBGDrivFindStream(psParams->u.pszName, psParams->bResetStream));
+
+       return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_WRITESTRING psParams;
+       IMG_UINT32 *pui32OutLen;
+       PDBG_STREAM psStream;
+
+       psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+       pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32OutLen = ExtDBGDrivWriteString(psStream,psParams->u.pszString,psParams->ui32Level);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32OutLen = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_WRITESTRING psParams;
+       IMG_UINT32 *pui32OutLen;
+       PDBG_STREAM psStream;
+
+       psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+       pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32OutLen = ExtDBGDrivWriteStringCM(psStream,psParams->u.pszString,psParams->ui32Level);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32OutLen = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 * pui32OutLen;
+       PDBG_IN_READSTRING      psParams;
+       PDBG_STREAM  psStream;
+
+       psParams = (PDBG_IN_READSTRING) pvInBuffer;
+       pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32OutLen = ExtDBGDrivReadString(psStream,
+                                                                                       psParams->u.pszString,psParams->ui32StringLen);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32OutLen = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *    pui32BytesCopied;
+       PDBG_IN_WRITE   psInParams;
+       PDBG_STREAM             psStream;
+
+       psInParams = (PDBG_IN_WRITE) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psInParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32BytesCopied = ExtDBGDrivWrite(psStream,
+                                                                               psInParams->u.pui8InBuffer,
+                                                                               psInParams->ui32TransferSize,
+                                                                               psInParams->ui32Level);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32BytesCopied = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *    pui32BytesCopied;
+       PDBG_IN_WRITE   psInParams;
+       PDBG_STREAM     psStream;
+
+       psInParams = (PDBG_IN_WRITE) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psInParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32BytesCopied = ExtDBGDrivWrite2(psStream,
+                                                                                psInParams->u.pui8InBuffer,
+                                                                                psInParams->ui32TransferSize,
+                                                                                psInParams->ui32Level);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32BytesCopied = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *    pui32BytesCopied;
+       PDBG_IN_WRITE   psInParams;
+       PDBG_STREAM             psStream;
+
+       psInParams = (PDBG_IN_WRITE) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psInParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32BytesCopied = ExtDBGDrivWriteCM(psStream,
+                                                                                 psInParams->u.pui8InBuffer,
+                                                                                 psInParams->ui32TransferSize,
+                                                                                 psInParams->ui32Level);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32BytesCopied = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivRead(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *    pui32BytesCopied;
+       PDBG_IN_READ    psInParams;
+       PDBG_STREAM             psStream;
+
+       psInParams = (PDBG_IN_READ) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psInParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32BytesCopied = ExtDBGDrivRead(psStream,
+                                                                          psInParams->bReadInitBuffer,
+                                                                          psInParams->ui32OutBufferSize,
+                                                                          psInParams->u.pui8OutBuffer);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32BytesCopied = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETDEBUGMODE    psParams;
+       PDBG_STREAM                             psStream;
+
+       psParams = (PDBG_IN_SETDEBUGMODE) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               ExtDBGDrivSetCaptureMode(psStream,
+                                                        psParams->ui32Mode,
+                                                        psParams->ui32Start,
+                                                        psParams->ui32End,
+                                                        psParams->ui32SampleRate);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETDEBUGOUTMODE psParams;
+       PDBG_STREAM                             psStream;
+
+       psParams = (PDBG_IN_SETDEBUGOUTMODE) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               ExtDBGDrivSetOutputMode(psStream,psParams->ui32Mode);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETDEBUGLEVEL psParams;
+       PDBG_STREAM           psStream;
+
+       psParams = (PDBG_IN_SETDEBUGLEVEL) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               ExtDBGDrivSetDebugLevel(psStream,psParams->ui32Level);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETFRAME        psParams;
+       PDBG_STREAM                     psStream;
+
+       psParams = (PDBG_IN_SETFRAME) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               ExtDBGDrivSetFrame(psStream,psParams->ui32Frame);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_STREAM  psStream;
+       IMG_UINT32  *pui32Current;
+
+       pui32Current = (IMG_UINT32 *) pvOutBuffer;
+       psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+       
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32Current = ExtDBGDrivGetFrame(psStream);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32Current = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_ISCAPTUREFRAME psParams;
+       IMG_UINT32 *                    pui32Current;
+       PDBG_STREAM                             psStream;
+
+       psParams = (PDBG_IN_ISCAPTUREFRAME) pvInBuffer;
+       pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32Current = ExtDBGDrivIsCaptureFrame(psStream,
+                                                                                        psParams->bCheckPreviousFrame);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32Current = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_OVERRIDEMODE    psParams;
+       PDBG_STREAM                             psStream;
+
+       psParams = (PDBG_IN_OVERRIDEMODE) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(     pvOutBuffer);
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               ExtDBGDrivOverrideMode(psStream,psParams->ui32Mode);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_STREAM  psStream;
+
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               ExtDBGDrivDefaultMode(psStream);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETMARKER       psParams;
+       PDBG_STREAM                     psStream;
+
+       psParams = (PDBG_IN_SETMARKER) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       psStream = SID2PStream(psParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               ExtDBGDrivSetMarker(psStream, psParams->ui32Marker);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_STREAM  psStream;
+       IMG_UINT32  *pui32Current;
+
+       pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32Current = ExtDBGDrivGetMarker(psStream);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32Current = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_PVOID *     ppvOut;
+
+       PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+       ppvOut = (IMG_PVOID *) pvOutBuffer;
+
+       *ppvOut = DBGDrivGetServiceTable();
+
+    return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_WRITE_LF psInParams;
+       IMG_UINT32      *pui32BytesCopied;
+       PDBG_STREAM      psStream;
+
+       psInParams = (PDBG_IN_WRITE_LF) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psInParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32BytesCopied = ExtDBGDrivWriteLF(psStream,
+                                                                                 psInParams->u.pui8InBuffer,
+                                                                                 psInParams->ui32BufferSize,
+                                                                                 psInParams->ui32Level,
+                                                                                 psInParams->ui32Flags);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *    pui32BytesCopied;
+       PDBG_IN_READ    psInParams;
+       PDBG_STREAM             psStream;
+
+       psInParams = (PDBG_IN_READ) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       psStream = SID2PStream(psInParams->hStream);
+       if (psStream != (PDBG_STREAM)IMG_NULL)
+       {
+               *pui32BytesCopied = ExtDBGDrivReadLF(psStream,
+                                                                                psInParams->ui32OutBufferSize,
+                                                                                psInParams->u.pui8OutBuffer);
+               return(IMG_TRUE);
+       }
+       else
+       {
+               
+               *pui32BytesCopied = 0;
+               return(IMG_FALSE);
+       }
+}
+
+static IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       DBG_EVENT eEvent = (DBG_EVENT)(*(IMG_UINT32 *)pvInBuffer);
+
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivWaitForEvent(eEvent);
+
+       return(IMG_TRUE);
+}
+
+IMG_UINT32 (*g_DBGDrivProc[25])(IMG_VOID *, IMG_VOID *) =
+{
+       DBGDIOCDrivCreateStream,
+       DBGDIOCDrivDestroyStream,
+       DBGDIOCDrivGetStream,
+       DBGDIOCDrivWriteString,
+       DBGDIOCDrivReadString,
+       DBGDIOCDrivWrite,
+       DBGDIOCDrivRead,
+       DBGDIOCDrivSetCaptureMode,
+       DBGDIOCDrivSetOutMode,
+       DBGDIOCDrivSetDebugLevel,
+       DBGDIOCDrivSetFrame,
+       DBGDIOCDrivGetFrame,
+       DBGDIOCDrivOverrideMode,
+       DBGDIOCDrivDefaultMode,
+       DBGDIOCDrivGetServiceTable,
+       DBGDIOCDrivWrite2,
+       DBGDIOCDrivWriteStringCM,
+       DBGDIOCDrivWriteCM,
+       DBGDIOCDrivSetMarker,
+       DBGDIOCDrivGetMarker,
+       DBGDIOCDrivIsCaptureFrame,
+       DBGDIOCDrivWriteLF,
+       DBGDIOCDrivReadLF,
+       DBGDIOCDrivWaitForEvent
+};
+
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c
new file mode 100644 (file)
index 0000000..a78f60a
--- /dev/null
@@ -0,0 +1,302 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope it will be useful but, except 
+ * as otherwise stated in writing, without any warranty; without even the 
+ * implied warranty of merchantability or fitness for a particular purpose. 
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/hardirq.h>
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#endif 
+
+#include "img_types.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "hostfunc.h"
+#include "dbgdriv.h"
+
+#if defined(MODULE) && defined(DEBUG) && !defined(SUPPORT_DRI_DRM)
+IMG_UINT32     gPVRDebugLevel = (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
+
+#define PVR_STRING_TERMINATOR          '\0'
+#define PVR_IS_FILE_SEPARATOR(character) ( ((character) == '\\') || ((character) == '/') )
+
+void PVRSRVDebugPrintf (
+                                               IMG_UINT32      ui32DebugLevel,
+                                               const IMG_CHAR* pszFileName,
+                                               IMG_UINT32      ui32Line,
+                                               const IMG_CHAR* pszFormat,
+                                               ...
+                                       )
+{
+       IMG_BOOL bTrace;
+#if !defined(__sh__)
+       IMG_CHAR *pszLeafName;
+
+       pszLeafName = (char *)strrchr (pszFileName, '\\');
+
+       if (pszLeafName)
+       {
+               pszFileName = pszLeafName;
+       }
+#endif 
+
+       bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
+
+       if (gPVRDebugLevel & ui32DebugLevel)
+       {
+               va_list vaArgs;
+               static char szBuffer[256];
+
+               va_start (vaArgs, pszFormat);
+
+               
+               if (bTrace == IMG_FALSE)
+               {
+                       switch(ui32DebugLevel)
+                       {
+                               case DBGPRIV_FATAL:
+                               {
+                                       strncpy (szBuffer, "PVR_K:(Fatal): ", sizeof (szBuffer));
+                                       break;
+                               }
+                               case DBGPRIV_ERROR:
+                               {
+                                       strncpy (szBuffer, "PVR_K:(Error): ", sizeof (szBuffer));
+                                       break;
+                               }
+                               case DBGPRIV_WARNING:
+                               {
+                                       strncpy (szBuffer, "PVR_K:(Warning): ", sizeof (szBuffer));
+                                       break;
+                               }
+                               case DBGPRIV_MESSAGE:
+                               {
+                                       strncpy (szBuffer, "PVR_K:(Message): ", sizeof (szBuffer));
+                                       break;
+                               }
+                               case DBGPRIV_VERBOSE:
+                               {
+                                       strncpy (szBuffer, "PVR_K:(Verbose): ", sizeof (szBuffer));
+                                       break;
+                               }
+                               default:
+                               {
+                                       strncpy (szBuffer, "PVR_K:(Unknown message level)", sizeof (szBuffer));
+                                       break;
+                               }
+                       }
+               }
+               else
+               {
+                       strncpy (szBuffer, "PVR_K: ", sizeof (szBuffer));
+               }
+
+               vsprintf (&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
+
+               
+               if (bTrace == IMG_FALSE)
+               {
+                       sprintf (&szBuffer[strlen(szBuffer)], " [%d, %s]", (int)ui32Line, pszFileName);
+               }
+
+               printk(KERN_INFO "%s\r\n", szBuffer);
+
+               va_end (vaArgs);
+       }
+}
+#endif 
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+       memset(pvDest, (int) ui8Value, (size_t) ui32Size);
+}
+
+IMG_VOID HostMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+    unsigned char *src,*dst;
+    int i;
+
+    src=(unsigned char *)pvSrc;
+    dst=(unsigned char *)pvDst;
+    for(i=0;i<ui32Size;i++)
+    {
+        dst[i]=src[i];
+    }
+#else
+    memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+IMG_UINT32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName, IMG_UINT32 *pui32Data)
+{
+    
+       return 0;
+}
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+    return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase)
+{
+    vfree(pvBase);
+}
+
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+    return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase)
+{
+    vfree(pvBase);
+}
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID **ppvMdl)
+{
+    
+       return IMG_NULL;
+}
+
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess)
+{
+    
+}
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID)
+{
+    
+}
+
+IMG_VOID * HostCreateMutex(IMG_VOID)
+{
+       struct semaphore *psSem;
+
+       psSem = kmalloc(sizeof(*psSem), GFP_KERNEL);
+       if (psSem)
+       {
+               init_MUTEX(psSem);
+       }
+
+       return psSem;
+}
+
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex)
+{
+       BUG_ON(in_interrupt());
+
+#if defined(PVR_DEBUG_DBGDRV_DETECT_HOST_MUTEX_COLLISIONS)
+       if (down_trylock((struct semaphore *)pvMutex))
+       {
+               printk(KERN_INFO "HostAquireMutex: Waiting for mutex\n");
+               down((struct semaphore *)pvMutex);
+       }
+#else
+       down((struct semaphore *)pvMutex);
+#endif
+}
+
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex)
+{
+       up((struct semaphore *)pvMutex);
+}
+
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex)
+{
+       if (pvMutex)
+       {
+               kfree(pvMutex);
+       }
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+#define        EVENT_WAIT_TIMEOUT_MS   500
+#define        EVENT_WAIT_TIMEOUT_JIFFIES      (EVENT_WAIT_TIMEOUT_MS * HZ / 1000)
+
+static int iStreamData;
+static wait_queue_head_t sStreamDataEvent;
+
+IMG_INT32 HostCreateEventObjects(IMG_VOID)
+{
+       init_waitqueue_head(&sStreamDataEvent);
+
+       return 0;
+}
+
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent)
+{
+       switch(eEvent)
+       {
+               case DBG_EVENT_STREAM_DATA:
+                       
+                       wait_event_interruptible_timeout(sStreamDataEvent, iStreamData != 0, EVENT_WAIT_TIMEOUT_JIFFIES);
+                       iStreamData = 0;
+                       break;
+               default:
+                       
+                       msleep_interruptible(EVENT_WAIT_TIMEOUT_MS);
+                       break;
+       }
+}
+
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent)
+{
+       switch(eEvent)
+       {
+               case DBG_EVENT_STREAM_DATA:
+                       iStreamData = 1;
+                       wake_up_interruptible(&sStreamDataEvent);
+                       break;
+               default:
+                       break;
+       }
+}
+
+IMG_VOID HostDestroyEventObjects(IMG_VOID)
+{
+}
+#endif 
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile
new file mode 100644 (file)
index 0000000..00db6ef
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+# 
+# This program is distributed in the hope it will be useful but, except 
+# as otherwise stated in writing, without any warranty; without even the 
+# implied warranty of merchantability or fitness for a particular purpose. 
+# See the GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Contact Information:
+# Imagination Technologies Ltd. <gpl-support@imgtec.com>
+# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
+# 
+#
+#
+
+MODULE         = dbgdrv
+
+INCLUDES = -I$(EURASIAROOT)/services4/srvkm/env/linux
+
+SOURCES        =
+                               
+include $(EURASIAROOT)/tools/intern/debug/dbgdriv/linux/makefile.linux.common
+
+include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/main.c b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/main.c
new file mode 100644 (file)
index 0000000..a3f7abb
--- /dev/null
@@ -0,0 +1,315 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+
+#if defined(LDM_PLATFORM) && !defined(SUPPORT_DRI_DRM)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(LDM_PCI) && !defined(SUPPORT_DRI_DRM)
+#include <linux/pci.h>
+#endif
+
+#include <asm/uaccess.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include "drmP.h"
+#include "drm.h"
+#endif
+
+#include "img_types.h"
+#include "linuxsrv.h"
+#include "dbgdriv_ioctl.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hostfunc.h"
+#include "hotkey.h"
+#include "pvr_debug.h"
+#include "pvrmodule.h"
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#else
+
+#define DRVNAME "dbgdrv"
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+static struct class *psDbgDrvClass;
+#endif
+
+static int AssignedMajorNumber = 0;
+
+long dbgdrv_ioctl(struct file *, unsigned int, unsigned long);
+
+static int dbgdrv_open(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+       return 0;
+}
+
+static int dbgdrv_release(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+       return 0;
+}
+
+static int dbgdrv_mmap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+       return 0;
+}
+
+static struct file_operations dbgdrv_fops = {
+       .owner          = THIS_MODULE,
+       .unlocked_ioctl = dbgdrv_ioctl,
+       .open           = dbgdrv_open,
+       .release        = dbgdrv_release,
+       .mmap           = dbgdrv_mmap,
+};
+
+#endif
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table)
+{
+       extern DBGKM_SERVICE_TABLE g_sDBGKMServices;
+
+       *fn_table = &g_sDBGKMServices;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+void dbgdrv_cleanup(void)
+#else
+static void __exit dbgdrv_cleanup(void)
+#endif
+{
+#if !defined(SUPPORT_DRI_DRM)
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+       device_destroy(psDbgDrvClass, MKDEV(AssignedMajorNumber, 0));
+       class_destroy(psDbgDrvClass);
+#endif
+       unregister_chrdev(AssignedMajorNumber, DRVNAME);
+#endif
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+       HostDestroyEventObjects();
+#endif
+       HostDestroyMutex(g_pvAPIMutex);
+       return;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT dbgdrv_init(void)
+#else
+static int __init dbgdrv_init(void)
+#endif
+{
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+       struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+       int err = -EBUSY;
+#endif
+
+
+       if ((g_pvAPIMutex=HostCreateMutex()) == IMG_NULL)
+       {
+               return -ENOMEM;
+       }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+       (void) HostCreateEventObjects();
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+       AssignedMajorNumber =
+       register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
+
+       if (AssignedMajorNumber <= 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR," unable to get major\n"));
+               goto ErrDestroyEventObjects;
+       }
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
+       psDbgDrvClass = class_create(THIS_MODULE, DRVNAME);
+       if (IS_ERR(psDbgDrvClass))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: unable to create class (%ld)",
+                                __func__, PTR_ERR(psDbgDrvClass)));
+               goto ErrUnregisterCharDev;
+       }
+
+       psDev = device_create(psDbgDrvClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+                                                 NULL,
+#endif
+                                                 DRVNAME);
+       if (IS_ERR(psDev))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: unable to create device (%ld)",
+                                                               __func__, PTR_ERR(psDev)));
+               goto ErrDestroyClass;
+       }
+#endif
+#endif
+
+       return 0;
+
+#if !defined(SUPPORT_DRI_DRM)
+ErrDestroyEventObjects:
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+       HostDestroyEventObjects();
+#endif
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ErrUnregisterCharDev:
+       unregister_chrdev(AssignedMajorNumber, DRVNAME);
+ErrDestroyClass:
+       class_destroy(psDbgDrvClass);
+#endif
+       return err;
+#endif
+}
+
+#if defined(SUPPORT_DRI_DRM)
+int dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+long dbgdrv_ioctl(struct file *file, unsigned int ioctlCmd, unsigned long arg)
+#endif
+{
+       IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
+       char *buffer, *in, *out;
+       unsigned int cmd;
+
+       if((pIP->ui32InBufferSize > (PAGE_SIZE >> 1) ) || (pIP->ui32OutBufferSize > (PAGE_SIZE >> 1)))
+       {
+               PVR_DPF((PVR_DBG_ERROR,"Sizes of the buffers are too large, cannot do ioctl\n"));
+               return -1;
+       }
+
+       buffer = (char *) HostPageablePageAlloc(1);
+       if(!buffer)
+       {
+               PVR_DPF((PVR_DBG_ERROR,"Failed to allocate buffer, cannot do ioctl\n"));
+               return -EFAULT;
+       }
+
+       in = buffer;
+       out = buffer + (PAGE_SIZE >>1);
+
+       if(copy_from_user(in, pIP->pInBuffer, pIP->ui32InBufferSize) != 0)
+       {
+               goto init_failed;
+       }
+
+       cmd = ((pIP->ui32Cmd >> 2) & 0xFFF) - 0x801;
+
+       if(pIP->ui32Cmd == DEBUG_SERVICE_READ)
+       {
+               IMG_UINT32 *pui32BytesCopied = (IMG_UINT32 *)out;
+               DBG_IN_READ *psReadInParams = (DBG_IN_READ *)in;
+               DBG_STREAM *psStream;
+               IMG_CHAR *ui8Tmp;
+
+               ui8Tmp = vmalloc(psReadInParams->ui32OutBufferSize);
+
+               if(!ui8Tmp)
+               {
+                       goto init_failed;
+               }
+
+               psStream = SID2PStream(psReadInParams->hStream);
+               if(!psStream)
+               {
+                       goto init_failed;
+               }
+
+               *pui32BytesCopied = ExtDBGDrivRead(psStream,
+                                                                                  psReadInParams->bReadInitBuffer,
+                                                                                  psReadInParams->ui32OutBufferSize,
+                                                                                  ui8Tmp);
+
+               if(copy_to_user(psReadInParams->u.pui8OutBuffer,
+                                               ui8Tmp,
+                                               *pui32BytesCopied) != 0)
+               {
+                       vfree(ui8Tmp);
+                       goto init_failed;
+               }
+
+               vfree(ui8Tmp);
+       }
+       else
+       {
+               (g_DBGDrivProc[cmd])(in, out);
+       }
+
+       if(copy_to_user(pIP->pOutBuffer, out, pIP->ui32OutBufferSize) != 0)
+       {
+               goto init_failed;
+       }
+
+       HostPageablePageFree((IMG_VOID *)buffer);
+       return 0;
+
+init_failed:
+       HostPageablePageFree((IMG_VOID *)buffer);
+       return -EFAULT;
+}
+
+
+IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey)
+{
+       PVR_UNREFERENCED_PARAMETER(hHotKey);
+}
+
+IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo)
+{
+       PVR_UNREFERENCED_PARAMETER(ui32ScanCode);
+       PVR_UNREFERENCED_PARAMETER(ui32ShiftState);
+       PVR_UNREFERENCED_PARAMETER(psInfo);
+}
+
+/*EXPORT_SYMBOL(DBGDrvGetServiceTable); */
+
+#if !defined(SUPPORT_DRI_DRM)
+subsys_initcall(dbgdrv_init);
+module_exit(dbgdrv_cleanup);
+#endif
diff --git a/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common b/drivers/staging/mrst/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common
new file mode 100644 (file)
index 0000000..0744af2
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful but, except
+# as otherwise stated in writing, without any warranty; without even the
+# implied warranty of merchantability or fitness for a particular purpose.
+# See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Contact Information:
+# Imagination Technologies Ltd. <gpl-support@imgtec.com>
+# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+#
+#
+#
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+DBGDRV_SOURCES_ROOT = $(KBUILDROOT)/../tools/intern/debug/dbgdriv
+else
+DBGDRV_SOURCES_ROOT = ../..
+endif
+
+INCLUDES +=    -I$(EURASIAROOT)/include4 \
+                       -I$(EURASIAROOT)/tools/intern/debug \
+                       -I$(EURASIAROOT)/tools/intern/debug/dbgdriv/common \
+                       -I$(EURASIAROOT)/tools/intern/debug/client
+
+SOURCES        +=      $(DBGDRV_SOURCES_ROOT)/linux/main.c \
+                               $(DBGDRV_SOURCES_ROOT)/common/dbgdriv.c \
+                               $(DBGDRV_SOURCES_ROOT)/common/ioctl.c \
+                               $(DBGDRV_SOURCES_ROOT)/common/handle.c \
+                               $(DBGDRV_SOURCES_ROOT)/linux/hostfunc.c \
+                               $(DBGDRV_SOURCES_ROOT)/common/hotkey.c
index 3933691..394b0f0 100644 (file)
@@ -3,6 +3,9 @@
  * OS abstraction macros.
  */
 
+#ifndef _DRM_OS_LINUX_H_
+#define _DRM_OS_LINUX_H_
+
 #include <linux/interrupt.h>   /* For task queue support */
 #include <linux/delay.h>
 
@@ -125,3 +128,5 @@ do {                                                                \
 
 #define DRM_WAKEUP( queue ) wake_up( queue )
 #define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
+
+#endif /* _DRM_OS_LINUX_H_ */