1.3.13.1607/3_00_00_08+flat+Lindent
authorImagination Technologies/TI <imgtec>
Sat, 19 May 2012 12:47:09 +0000 (15:47 +0300)
committerGrazvydas Ignotas <notasas@gmail.com>
Sat, 19 May 2012 12:47:50 +0000 (15:47 +0300)
116 files changed:
pvr/COPYING [new file with mode: 0644]
pvr/INSTALL [new file with mode: 0644]
pvr/Kbuild [new file with mode: 0644]
pvr/Makefile [new file with mode: 0644]
pvr/README [new file with mode: 0644]
pvr/bridged_pvr_bridge.c [new file with mode: 0644]
pvr/bridged_pvr_bridge.h [new file with mode: 0644]
pvr/buffer_manager.c [new file with mode: 0644]
pvr/buffer_manager.h [new file with mode: 0644]
pvr/bufferclass_example.c [new file with mode: 0644]
pvr/bufferclass_example.h [new file with mode: 0644]
pvr/bufferclass_example_linux.c [new file with mode: 0644]
pvr/bufferclass_example_linux.h [new file with mode: 0644]
pvr/bufferclass_example_private.c [new file with mode: 0644]
pvr/dbgdrvif.h [new file with mode: 0644]
pvr/device.h [new file with mode: 0644]
pvr/deviceclass.c [new file with mode: 0644]
pvr/devicemem.c [new file with mode: 0644]
pvr/env_data.h [new file with mode: 0644]
pvr/event.c [new file with mode: 0644]
pvr/event.h [new file with mode: 0644]
pvr/handle.c [new file with mode: 0644]
pvr/handle.h [new file with mode: 0644]
pvr/hash.c [new file with mode: 0644]
pvr/hash.h [new file with mode: 0644]
pvr/img_defs.h [new file with mode: 0644]
pvr/img_types.h [new file with mode: 0644]
pvr/ioctldef.h [new file with mode: 0644]
pvr/kernelbuffer.h [new file with mode: 0644]
pvr/kerneldisplay.h [new file with mode: 0644]
pvr/mem.c [new file with mode: 0644]
pvr/metrics.c [new file with mode: 0644]
pvr/metrics.h [new file with mode: 0644]
pvr/mm.c [new file with mode: 0644]
pvr/mm.h [new file with mode: 0644]
pvr/mmap.c [new file with mode: 0644]
pvr/mmap.h [new file with mode: 0644]
pvr/mmu.c [new file with mode: 0644]
pvr/mmu.h [new file with mode: 0644]
pvr/module.c [new file with mode: 0644]
pvr/modules.order [new file with mode: 0644]
pvr/mutex.c [new file with mode: 0644]
pvr/mutex.h [new file with mode: 0644]
pvr/oemfuncs.h [new file with mode: 0644]
pvr/omaplfb.h [new file with mode: 0644]
pvr/omaplfb_displayclass.c [new file with mode: 0644]
pvr/omaplfb_linux.c [new file with mode: 0644]
pvr/osfunc.c [new file with mode: 0644]
pvr/osfunc.h [new file with mode: 0644]
pvr/pb.c [new file with mode: 0644]
pvr/pdump.c [new file with mode: 0644]
pvr/pdump_km.h [new file with mode: 0644]
pvr/pdumpdefs.h [new file with mode: 0644]
pvr/perproc.c [new file with mode: 0644]
pvr/perproc.h [new file with mode: 0644]
pvr/power.c [new file with mode: 0644]
pvr/power.h [new file with mode: 0644]
pvr/proc.c [new file with mode: 0644]
pvr/proc.h [new file with mode: 0644]
pvr/pvr_bridge.h [new file with mode: 0644]
pvr/pvr_bridge_k.c [new file with mode: 0644]
pvr/pvr_bridge_km.h [new file with mode: 0644]
pvr/pvr_debug.c [new file with mode: 0644]
pvr/pvr_debug.h [new file with mode: 0644]
pvr/pvrmmap.h [new file with mode: 0644]
pvr/pvrmodule.h [new file with mode: 0644]
pvr/pvrsrv.c [new file with mode: 0644]
pvr/pvrversion.h [new file with mode: 0644]
pvr/queue.c [new file with mode: 0644]
pvr/queue.h [new file with mode: 0644]
pvr/ra.c [new file with mode: 0644]
pvr/ra.h [new file with mode: 0644]
pvr/regpaths.h [new file with mode: 0644]
pvr/resman.c [new file with mode: 0644]
pvr/resman.h [new file with mode: 0644]
pvr/services.h [new file with mode: 0644]
pvr/services_headers.h [new file with mode: 0644]
pvr/servicesext.h [new file with mode: 0644]
pvr/servicesint.h [new file with mode: 0644]
pvr/sgx530defs.h [new file with mode: 0644]
pvr/sgx_bridge.h [new file with mode: 0644]
pvr/sgx_bridge_km.h [new file with mode: 0644]
pvr/sgxapi_km.h [new file with mode: 0644]
pvr/sgxconfig.h [new file with mode: 0644]
pvr/sgxcoretypes.h [new file with mode: 0644]
pvr/sgxdefs.h [new file with mode: 0644]
pvr/sgxerrata.h [new file with mode: 0644]
pvr/sgxfeaturedefs.h [new file with mode: 0644]
pvr/sgxinfo.h [new file with mode: 0644]
pvr/sgxinfokm.h [new file with mode: 0644]
pvr/sgxinit.c [new file with mode: 0644]
pvr/sgxkick.c [new file with mode: 0644]
pvr/sgxmmu.h [new file with mode: 0644]
pvr/sgxreset.c [new file with mode: 0644]
pvr/sgxscript.h [new file with mode: 0644]
pvr/sgxtransfer.c [new file with mode: 0644]
pvr/sgxutils.c [new file with mode: 0644]
pvr/sgxutils.h [new file with mode: 0644]
pvr/srvkm.h [new file with mode: 0644]
pvr/syscommon.h [new file with mode: 0644]
pvr/sysconfig.c [new file with mode: 0644]
pvr/sysconfig.h [new file with mode: 0644]
pvr/sysinfo.h [new file with mode: 0644]
pvr/syslocal.h [new file with mode: 0644]
pvr/sysutils.c [new file with mode: 0644]
pvr/sysutils_linux.c [new file with mode: 0644]
pvr/tools/dbgdriv.c [new file with mode: 0644]
pvr/tools/dbgdriv.h [new file with mode: 0644]
pvr/tools/hostfunc.c [new file with mode: 0644]
pvr/tools/hostfunc.h [new file with mode: 0644]
pvr/tools/hotkey.c [new file with mode: 0644]
pvr/tools/hotkey.h [new file with mode: 0644]
pvr/tools/ioctl.c [new file with mode: 0644]
pvr/tools/ioctl.h [new file with mode: 0644]
pvr/tools/linuxsrv.h [new file with mode: 0644]
pvr/tools/main.c [new file with mode: 0644]

diff --git a/pvr/COPYING b/pvr/COPYING
new file mode 100644 (file)
index 0000000..84ac8ec
--- /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/pvr/INSTALL b/pvr/INSTALL
new file mode 100644 (file)
index 0000000..bd08a56
--- /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/pvr/Kbuild b/pvr/Kbuild
new file mode 100644 (file)
index 0000000..19f9a24
--- /dev/null
@@ -0,0 +1,53 @@
+obj-m  := pvrsrvkm.o
+
+FILES := \
+services4/srvkm/common/queue.c \
+services4/srvkm/common/hash.c \
+services4/srvkm/common/perproc.c \
+services4/srvkm/common/mem.c \
+services4/srvkm/common/power.c \
+services4/srvkm/common/deviceclass.c \
+services4/srvkm/common/metrics.c \
+services4/srvkm/common/resman.c \
+services4/srvkm/common/buffer_manager.c \
+services4/srvkm/common/pvrsrv.c \
+services4/srvkm/common/handle.c \
+services4/srvkm/common/ra.c \
+services4/srvkm/common/devicemem.c \
+services4/srvkm/env/linux/pvr_debug.c \
+services4/srvkm/env/linux/mm.c \
+services4/srvkm/env/linux/mutex.c \
+services4/srvkm/env/linux/mmap.c \
+services4/srvkm/env/linux/module.c \
+services4/srvkm/env/linux/proc.c \
+services4/srvkm/env/linux/event.c \
+services4/srvkm/env/linux/osfunc.c \
+services4/srvkm/env/linux/pvr_bridge_k.c \
+services4/srvkm/env/linux/pdump.c \
+services4/srvkm/devices/sgx/sgxtransfer.c \
+services4/srvkm/devices/sgx/sgxinit.c \
+services4/srvkm/devices/sgx/sgxutils.c \
+services4/srvkm/devices/sgx/pb.c \
+services4/srvkm/devices/sgx/sgxkick.c \
+services4/srvkm/devices/sgx/mmu.c \
+services4/srvkm/devices/sgx/sgxreset.c \
+services4/srvkm/bridged/bridged_pvr_bridge.c \
+services4/system/omap3430/sysutils_linux.c \
+services4/system/omap3430/sysconfig.c
+
+EXTRA_CFLAGS += -I$(src)/include4
+EXTRA_CFLAGS += -I$(src)/services4/include
+EXTRA_CFLAGS += -I$(src)/services4/srvkm/include
+EXTRA_CFLAGS += -I$(src)/services4/srvkm/hwdefs
+EXTRA_CFLAGS += -I$(src)/services4/srvkm/bridged
+EXTRA_CFLAGS += -I$(src)/services4/srvkm/devices/sgx
+EXTRA_CFLAGS += -I$(src)/services4/srvkm/env/linux
+EXTRA_CFLAGS += -I$(src)/services4/system/include
+EXTRA_CFLAGS += -I$(src)/services4/system/omap3430
+
+EXTRA_CFLAGS += $(ALL_CFLAGS)
+
+pvrsrvkm-y     := $(FILES:.c=.o)
+
+obj-y := services4/3rdparty/dc_omap3430_linux/
+
diff --git a/pvr/Makefile b/pvr/Makefile
new file mode 100644 (file)
index 0000000..7f5271d
--- /dev/null
@@ -0,0 +1,157 @@
+export DISCIMAGE =  /home/pratheesh/nfsexport/glibc_rootfs
+
+export KERNELDIR = /home1/pratheesh/workdir/opt/linux/kernel_org/REL_OMAP35x_02.01.00.04/src/kernel/linux-02.01.00.04
+export KERNEL_PATH=$(KERNELDIR)
+export KERNEL_SRC=$(KERNELDIR)
+export KDIR=$(KERNELDIR)
+
+export BUILD = debug
+
+export KBUILD_EXTRA_SYMBOLS = `pwd`/services4/srvkm/env/linux/kbuild/Module.symvers
+
+SGXCORE = 530
+CORE = -DSGX530 -DSUPPORT_SGX530 -DSGX_CORE_REV=103
+
+SUPPORT_SGX = 1
+SUPPORT_HW_RECOVERY = 1
+SUPPORT_SGX_HWPERF = 1
+SYS_USING_INTERRUPTS = 1
+SUPPORT_TI_PM = 0
+
+PVR2D_ALT_2DHW = 1
+
+LDM_PLATFORM ?= 1
+
+# Only enable active power management if passive power management is
+# enabled, as indicated by LDM_PLATFORM being set to 1.  On OMAP,
+# the system can suspend in the case where active power management is
+# enabled in the SGX driver, but passive power management isn't. As
+# passive power management isn't enabled, the driver won't see the
+# system suspend/resume events, and so won't take appropriate action.
+ifeq ($(LDM_PLATFORM),1)
+SUPPORT_ACTIVE_POWER_MANAGEMENT ?= 1
+else
+SUPPORT_ACTIVE_POWER_MANAGEMENT = 0
+endif
+
+export PVR_BUILD_DIR := $(shell pwd)
+
+DATE := $(shell date "+%a %B %d %Z %Y" )
+
+CBUILD                 =       -DPVR_BUILD_DIR="\"$(PVR_BUILD_DIR)\"" \
+                               -DPVR_BUILD_DATE="\"$(DATE)\"" \
+                               -DPVR_BUILD_TYPE="\"$(BUILD)\""
+
+#  Don't support HW recovery on debug builds
+CBUILD.debug   = -DDEBUG
+CBUILD.timing  = -DTIMING
+CBUILD.release = -DRELEASE
+CFLAGS.debug   = -g -O0 -DDLL_METRIC=1
+CFLAGS.timing  = $(OPTIM) -g -DDLL_METRIC=1 -DTIMING
+CFLAGS.release = $(OPTIM) -g
+CFLAGS          = $(CFLAGS.$(BUILD))
+
+
+ifeq ("$(BUILD)", "debug")
+DEBUG_LINUX_MEMORY_ALLOCATIONS ?= 1
+DEBUG_LINUX_MEM_AREAS          ?= 1
+DEBUG_LINUX_MMAP_AREAS         ?= 1
+DEBUG_LINUX_XML_PROC_FILES     ?= 0
+DEBUG_LINUX_SLAB_ALLOCATIONS   ?= 0
+DEBUG_BRIDGE_KM                        ?= 1
+DEBUG_TRACE_BRIDGE_KM          ?= 0
+DEBUG_BRIDGE_KM_DISPATCH_TABLE ?= 0
+endif
+
+TRANSFER_QUEUE                 ?= 1
+SUPPORT_SGX_EVENT_OBJECT       ?= 1
+SUPPORT_SECURE_HANDLES         ?= 1
+SUPPORT_SRVINIT                        = 1
+SUPPORT_PERCONTEXT_PB          = 1
+
+SYS_CFLAGS += -DSERVICES4 -D_XOPEN_SOURCE=600 -DPVR2D_VALIDATE_INPUT_PARAMS
+
+# Thread support
+USE_PTHREADS ?= 1
+USE_GCC__thread_KEYWORD ?= 0
+OPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP ?= 0
+DISABLE_THREADS ?= 0
+
+# Automatically define C compiler macros for features possible (or not) in use.
+
+SYS_CFLAGS.$(SUPPORT_SRVINIT)                          += -DSUPPORT_SRVINIT
+
+SYS_CFLAGS.$(SUPPORT_SGX)                              += -DSUPPORT_SGX
+SYS_CFLAGS.$(SUPPORT_XWS)                              += -DSUPPORT_XWS
+SYS_CFLAGS.$(PDUMP)                                    += -DPDUMP
+SYS_CFLAGS.$(SUPPORT_POWER_MANAGEMENT)                 += -DSUPPORT_POWER_MANAGEMENT
+SYS_CFLAGS.$(SUPPORT_BUFFER_CLASS)                     += -DSUPPORT_BUFFER_CLASS
+
+SYS_CFLAGS.$(SUPPORT_PERCONTEXT_PB)                    += -DSUPPORT_PERCONTEXT_PB 
+SYS_CFLAGS.$(SUPPORT_DYNAMIC_PBRESIZE)                 += -DSUPPORT_DYNAMIC_PBRESIZE
+
+SYS_CFLAGS.$(USE_FBDEV)                                        += -DUSE_FBDEV
+SYS_CFLAGS.$(USE_FBDEV)                                        += -DFBDEV_NAME="\"$(FBDEV_NAME)\""
+SYS_CFLAGS.$(SUPPORT_DYNAMIC_3DCLOCKGATING)            += -DSUPPORT_DYNAMIC_3DCLOCKGATING
+SYS_CFLAGS.$(REENTRANCY_PROTECTION)                    += -DREENTRANCY_PROTECTION
+SYS_CFLAGS.$(SCHEDULER_CONTROL_SUPPORT)                += -DSCHEDULER_CONTROL_SUPPORT
+SYS_CFLAGS.$(USE_IMG_POWER_DOMAIN_FUNCTION)            += -DUSE_IMG_POWER_DOMAIN_FUNCTION
+
+SYS_CFLAGS.$(USE_DMALLOC)                              += -DDMALLOC
+
+SYS_CFLAGS.$(DEBUG_LINUX_MEMORY_ALLOCATIONS)           += -DDEBUG_LINUX_MEMORY_ALLOCATIONS
+SYS_CFLAGS.$(DEBUG_LINUX_MEM_AREAS)                    += -DDEBUG_LINUX_MEM_AREAS
+SYS_CFLAGS.$(DEBUG_LINUX_MMAP_AREAS)                   += -DDEBUG_LINUX_MMAP_AREAS
+SYS_CFLAGS.$(DEBUG_LINUX_XML_PROC_FILES)               += -DDEBUG_LINUX_XML_PROC_FILES
+SYS_CFLAGS.$(DEBUG_LINUX_SLAB_ALLOCATIONS)             += -DDEBUG_LINUX_SLAB_ALLOCATIONS
+SYS_CFLAGS.$(DEBUG_BRIDGE_KM)                          += -DDEBUG_BRIDGE_KM
+SYS_CFLAGS.$(DEBUG_TRACE_BRIDGE_KM)                    += -DDEBUG_TRACE_BRIDGE_KM
+SYS_CFLAGS.$(DEBUG_BRIDGE_KM_DISPATCH_TABLE)           += -DDEBUG_BRIDGE_KM_DISPATCH_TABLE
+
+SYS_CFLAGS.$(SUPPORT_LINUX_X86_WRITECOMBINE)           += -DSUPPORT_LINUX_X86_WRITECOMBINE
+
+SYS_CFLAGS.$(SGX_PDS_EVENTS_DISABLED)                  += -DSGX_PDS_EVENTS_DISABLED
+SYS_CFLAGS.$(USE_SUPPORT_NO_TA3D_OVERLAP)              += -DUSE_SUPPORT_NO_TA3D_OVERLAP
+SYS_CFLAGS.$(SUPPORT_SGX_TILING)                       += -DSUPPORT_SGX_TILING
+SYS_CFLAGS.$(TRANSFER_QUEUE)                           += -DTRANSFER_QUEUE
+
+SYS_CFLAGS.$(SUPPORT_SGX_MMU_DUMMY_PAGE)               += -DSUPPORT_SGX_MMU_DUMMY_PAGE
+
+SYS_CFLAGS.$(PVRSRV_USSE_EDM_STATUS_DEBUG)             += -DPVRSRV_USSE_EDM_STATUS_DEBUG
+
+SYS_CFLAGS.$(SUPPORT_DRI_DRM)                          += -DSUPPORT_DRI_DRM
+
+SYS_CFLAGS.$(SYS_USING_INTERRUPTS)                     += -DSYS_USING_INTERRUPTS
+SYS_CFLAGS.$(SUPPORT_HW_RECOVERY)                      += -DSUPPORT_HW_RECOVERY
+SYS_CFLAGS.$(SUPPORT_ACTIVE_POWER_MANAGEMENT)          += -DSUPPORT_ACTIVE_POWER_MANAGEMENT
+
+SYS_CFLAGS.$(SUPPORT_SECURE_HANDLES)                   += -DPVR_SECURE_HANDLES
+
+SYS_CFLAGS.$(USE_PTHREADS)                             += -DUSE_PTHREADS
+SYS_CFLAGS.$(USE_GCC__thread_KEYWORD)                  += -DUSE_GCC__thread_KEYWORD
+SYS_CFLAGS.$(OPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP)       += -DOPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP
+SYS_CFLAGS.$(DISABLE_THREADS)                          += -DDISABLE_THREADS
+SYS_CFLAGS.$(SUPPORT_SGX_EVENT_OBJECT)                 += -DSUPPORT_SGX_EVENT_OBJECT
+SYS_CFLAGS.$(LDM_PLATFORM)                             += -DLDM_PLATFORM
+SYS_CFLAGS.$(LDM_PCI)                                  += -DLDM_PCI
+SYS_CFLAGS.$(PVR_MANUAL_POWER_CONTROL)                 += -DPVR_MANUAL_POWER_CONTROL
+
+SYS_CFLAGS.$(PVR2D_ALT_2DHW)                           += -DPVR2D_ALT_2DHW
+
+SYS_CFLAGS.$(SUPPORT_SGX_HWPERF)                       += -DSUPPORT_SGX_HWPERF
+
+SYS_CFLAGS.$(SUPPORT_TI_PM)                             += -DSUPPORT_TI_PM
+
+export ALL_CFLAGS =    -DLINUX \
+                       $(CBUILD) $(CBUILD.$(BUILD)) \
+                       $(SYS_CFLAGS) $(SYS_CFLAGS.1) \
+                       $(MODULE_CFLAGS) $(MODULE_CFLAGS.$(BUILD)) \
+                       $(CORE) \
+                       $(CFLAGS)
+
+all:
+       $(MAKE) -C $(KERNELDIR) M=`pwd` $*
+
+clean:
+       $(MAKE) -C $(KERNELDIR) M=`pwd` clean
+
diff --git a/pvr/README b/pvr/README
new file mode 100644 (file)
index 0000000..788a703
--- /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/pvr/bridged_pvr_bridge.c b/pvr/bridged_pvr_bridge.c
new file mode 100644 (file)
index 0000000..f651cf7
--- /dev/null
@@ -0,0 +1,5017 @@
+/**********************************************************************
+ *
+ * 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"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "sgx_bridge_km.h"
+#include "pdump_km.h"
+#include "sgxutils.h"
+#include "mmu.h"
+
+#include "bridged_pvr_bridge.h"
+#include "env_data.h"
+
+#if defined (__linux__)
+#include "mmap.h"
+#else
+#define PVRMMapKVIndexAddressToMMapData(A,B,C,D,E) PVRSRV_OK
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+#ifndef ENOTTY
+#define ENOTTY 25
+#endif
+
+#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
+
+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];
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+static 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);
+}
+
+static 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);
+}
+#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)
+
+#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);
+       }
+}
+
+static 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 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 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_GENERIC;
+               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;
+}
+
+static 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
+#if defined(PVR_SECURE_HANDLES)
+                                          , abSharedDeviceMemHeap
+#endif
+           );
+
+       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 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 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]
+#if defined(PVR_SECURE_HANDLES)
+                                        , abSharedDeviceMemHeap
+#endif
+           );
+
+       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)
+int
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+                      PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM * psAllocDeviceMemIN,
+                      PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM * psAllocDeviceMemOUT,
+                      PVRSRV_PER_PROCESS_DATA * psPerProc);
+#else
+static 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));
+
+       if (psMemInfo->pvLinAddrKM) {
+               psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psMemInfo->pvLinAddrKM;
+       } else {
+               psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psMemInfo->sMemBlk.hOSMemHandle;
+       }
+#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;
+               psAllocDeviceMemOUT->psKernelSyncInfo = IMG_NULL;
+       } else {
+
+               psAllocDeviceMemOUT->psKernelSyncInfo =
+                   psMemInfo->psKernelSyncInfo;
+
+               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 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 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(psPerProc->psHandleBase,
+                                                   (IMG_VOID **) &
+                                                   psSrcKernelMemInfo,
+                                                   psMapDevMemIN->
+                                                   psSrcKernelMemInfo,
+                                                   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));
+
+       if (psDstKernelMemInfo->pvLinAddrKM) {
+               psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+                   psDstKernelMemInfo->pvLinAddrKM;
+       } else {
+               psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+                   psDstKernelMemInfo->sMemBlk.hOSMemHandle;
+       }
+       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;
+       psMapDevMemOUT->psDstKernelSyncInfo = IMG_NULL;
+
+       if (psDstKernelMemInfo->psKernelSyncInfo) {
+               psMapDevMemOUT->psDstKernelSyncInfo =
+                   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 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 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;
+       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;
+       }
+
+       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_GENERIC;
+               return 0;
+       }
+
+       psMapDevClassMemOUT->eError =
+           PVRSRVMapDeviceClassMemoryKM(psPerProc,
+                                        hDeviceClassBufferInt,
+                                        &psMemInfo, &hOSMapInfo);
+
+       if (psMapDevClassMemOUT->eError != PVRSRV_OK) {
+               return 0;
+       }
+
+       OSMemSet(&psMapDevClassMemOUT->sClientMemInfo,
+                0, sizeof(psMapDevClassMemOUT->sClientMemInfo));
+       OSMemSet(&psMapDevClassMemOUT->sClientSyncInfo,
+                0, sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+       if (psMemInfo->pvLinAddrKM) {
+               psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psMemInfo->pvLinAddrKM;
+       } else {
+               psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psMemInfo->sMemBlk.hOSMemHandle;
+       }
+       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;
+       psMapDevClassMemOUT->psKernelSyncInfo = IMG_NULL;
+
+       if (psMemInfo->psKernelSyncInfo) {
+               psMapDevClassMemOUT->psKernelSyncInfo =
+                   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 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)
+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 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;
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+       IMG_UINT32 ui32PageTableSize = 0;
+       IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;;
+
+       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;
+       }
+
+       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));
+
+               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,
+                                 psWrapExtMemIN->ui32ByteSize,
+                                 psWrapExtMemIN->ui32PageOffset,
+                                 psWrapExtMemIN->bPhysContig,
+                                 psSysPAddr,
+                                 psWrapExtMemIN->pvLinAddr, &psMemInfo);
+       if (psWrapExtMemIN->ui32NumPageTableEntries) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         ui32PageTableSize, (IMG_VOID *) psSysPAddr, 0);
+       }
+       if (psWrapExtMemOUT->eError != PVRSRV_OK) {
+               return 0;
+       }
+
+       if (psMemInfo->pvLinAddrKM) {
+               psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psMemInfo->pvLinAddrKM;
+       } else {
+               psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psMemInfo->sMemBlk.hOSMemHandle;
+       }
+
+       psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
+       psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+       psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+       psWrapExtMemOUT->sClientMemInfo.ui32AllocSize =
+           psMemInfo->ui32AllocSize;
+       psWrapExtMemOUT->sClientMemInfo.hMappingInfo = IMG_NULL;
+
+       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 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 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 int
+PVRMMapKVIndexAddressToMMapDataBW(IMG_UINT32 ui32BridgeID,
+                                 PVRSRV_BRIDGE_IN_KV_TO_MMAP_DATA *
+                                 psMMapDataIN,
+                                 PVRSRV_BRIDGE_OUT_KV_TO_MMAP_DATA *
+                                 psMMapDataOUT,
+                                 PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_KV_TO_MMAP_DATA);
+       PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psMMapDataOUT->eError =
+           PVRMMapKVIndexAddressToMMapData(psMMapDataIN->pvKVIndexAddress,
+                                           psMMapDataIN->ui32Bytes,
+                                           &psMMapDataOUT->ui32MMapOffset,
+                                           &psMMapDataOUT->ui32ByteOffset,
+                                           &psMMapDataOUT->ui32RealByteSize);
+
+       return 0;
+}
+
+#ifdef PDUMP
+static 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 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 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 int
+PDumpRegWithFlagsBW(IMG_UINT32 ui32BridgeID,
+                   PVRSRV_BRIDGE_IN_PDUMP_DUMPREG * psPDumpRegDumpIN,
+                   PVRSRV_BRIDGE_RETURN * psRetOUT,
+                   PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psRetOUT->eError =
+           PDumpRegWithFlagsKM(psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+                               psPDumpRegDumpIN->sHWReg.ui32RegVal,
+                               psPDumpRegDumpIN->ui32Flags);
+
+       return 0;
+}
+
+static int
+PDumpRegPolBW(IMG_UINT32 ui32BridgeID,
+             PVRSRV_BRIDGE_IN_PDUMP_REGPOL * psPDumpRegPolIN,
+             PVRSRV_BRIDGE_RETURN * psRetOUT,
+             PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psRetOUT->eError =
+           PDumpRegPolWithFlagsKM(psPDumpRegPolIN->sHWReg.ui32RegAddr,
+                                  psPDumpRegPolIN->sHWReg.ui32RegVal,
+                                  psPDumpRegPolIN->ui32Mask,
+                                  psPDumpRegPolIN->ui32Flags);
+
+       return 0;
+}
+
+static 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,
+                         PDUMP_POLL_OPERATOR_EQUAL,
+                         psPDumpMemPolIN->bLastFrame,
+                         psPDumpMemPolIN->bOverwrite,
+                         MAKEUNIQUETAG(pvMemInfo));
+
+       return 0;
+}
+
+static int
+PDumpMemBW(IMG_UINT32 ui32BridgeID,
+          PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM * psPDumpMemDumpIN,
+          PVRSRV_BRIDGE_RETURN * psRetOUT, PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       IMG_VOID *pvMemInfo;
+       IMG_VOID *pvAltLinAddrKM = IMG_NULL;
+       IMG_UINT32 ui32Bytes = psPDumpMemDumpIN->ui32Bytes;
+       IMG_HANDLE hBlockAlloc = 0;
+
+       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;
+       }
+
+       if (psPDumpMemDumpIN->pvAltLinAddr) {
+               if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                              ui32Bytes,
+                              &pvAltLinAddrKM, &hBlockAlloc) != PVRSRV_OK) {
+                       return -EFAULT;
+               }
+
+               if (CopyFromUserWrapper(psPerProc,
+                                       ui32BridgeID,
+                                       pvAltLinAddrKM,
+                                       psPDumpMemDumpIN->pvAltLinAddr,
+                                       ui32Bytes) != PVRSRV_OK) {
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32Bytes,
+                                 pvAltLinAddrKM, hBlockAlloc);
+                       return -EFAULT;
+               }
+       }
+
+       psRetOUT->eError =
+           PDumpMemKM(pvAltLinAddrKM,
+                      pvMemInfo,
+                      psPDumpMemDumpIN->ui32Offset,
+                      ui32Bytes,
+                      psPDumpMemDumpIN->ui32Flags, MAKEUNIQUETAG(pvMemInfo));
+
+       if (pvAltLinAddrKM) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32Bytes, pvAltLinAddrKM,
+                         hBlockAlloc);
+       }
+
+       return 0;
+}
+
+static int
+PDumpBitmapBW(IMG_UINT32 ui32BridgeID,
+             PVRSRV_BRIDGE_IN_PDUMP_BITMAP * psPDumpBitmapIN,
+             PVRSRV_BRIDGE_RETURN * psRetOUT,
+             PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+       PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+       psRetOUT->eError =
+           PDumpBitmapKM(&psPDumpBitmapIN->szFileName[0],
+                         psPDumpBitmapIN->ui32FileOffset,
+                         psPDumpBitmapIN->ui32Width,
+                         psPDumpBitmapIN->ui32Height,
+                         psPDumpBitmapIN->ui32StrideInBytes,
+                         psPDumpBitmapIN->sDevBaseAddr,
+                         psPDumpBitmapIN->ui32Size,
+                         psPDumpBitmapIN->ePixelFormat,
+                         psPDumpBitmapIN->eMemFormat,
+                         psPDumpBitmapIN->ui32Flags);
+
+       return 0;
+}
+
+static int
+PDumpReadRegBW(IMG_UINT32 ui32BridgeID,
+              PVRSRV_BRIDGE_IN_PDUMP_READREG * psPDumpReadRegIN,
+              PVRSRV_BRIDGE_RETURN * psRetOUT,
+              PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       psRetOUT->eError =
+           PDumpReadRegKM(&psPDumpReadRegIN->szFileName[0],
+                          psPDumpReadRegIN->ui32FileOffset,
+                          psPDumpReadRegIN->ui32Address,
+                          psPDumpReadRegIN->ui32Size,
+                          psPDumpReadRegIN->ui32Flags);
+
+       return 0;
+}
+
+static 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 int
+PDumpSyncDumpBW(IMG_UINT32 ui32BridgeID,
+               PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC * psPDumpSyncDumpIN,
+               PVRSRV_BRIDGE_RETURN * psRetOUT,
+               PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       IMG_VOID *pvAltLinAddrKM = IMG_NULL;
+       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;
+       }
+
+       if (psPDumpSyncDumpIN->pvAltLinAddr) {
+               if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                              ui32Bytes, &pvAltLinAddrKM, 0) != PVRSRV_OK) {
+                       return -EFAULT;
+               }
+
+               if (CopyFromUserWrapper(psPerProc,
+                                       ui32BridgeID,
+                                       pvAltLinAddrKM,
+                                       psPDumpSyncDumpIN->pvAltLinAddr,
+                                       ui32Bytes) != PVRSRV_OK) {
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32Bytes,
+                                 pvAltLinAddrKM, 0);
+                       return -EFAULT;
+               }
+       }
+
+       psRetOUT->eError =
+           PDumpMemKM(pvAltLinAddrKM,
+                      ((PVRSRV_KERNEL_SYNC_INFO *) pvSyncInfo)->
+                      psSyncDataMemInfoKM, psPDumpSyncDumpIN->ui32Offset,
+                      ui32Bytes, 0,
+                      MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *) pvSyncInfo)->
+                                    psSyncDataMemInfoKM));
+
+       if (pvAltLinAddrKM) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32Bytes, pvAltLinAddrKM,
+                         0);
+       }
+
+       return 0;
+}
+
+static 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,
+                         IMG_FALSE, IMG_FALSE,
+                         MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)
+                                        pvSyncInfo)->psSyncDataMemInfoKM));
+
+       return 0;
+}
+
+static int
+PDumpPDRegBW(IMG_UINT32 ui32BridgeID,
+            PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG * psPDumpPDRegDumpIN,
+            PVRSRV_BRIDGE_RETURN * psRetOUT,
+            PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PDREG);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       PDumpPDReg(psPDumpPDRegDumpIN->sHWReg.ui32RegAddr,
+                  psPDumpPDRegDumpIN->sHWReg.ui32RegVal, PDUMP_PD_UNIQUETAG);
+
+       psRetOUT->eError = PVRSRV_OK;
+       return 0;
+}
+
+static int
+PDumpCycleCountRegReadBW(IMG_UINT32 ui32BridgeID,
+                        PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ *
+                        psPDumpCycleCountRegReadIN,
+                        PVRSRV_BRIDGE_RETURN * psRetOUT,
+                        PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+                                PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+       PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+       PDumpCycleCountRegRead(psPDumpCycleCountRegReadIN->ui32RegOffset,
+                              psPDumpCycleCountRegReadIN->bLastFrame);
+
+       psRetOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+static 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 int
+PDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
+                  PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY * psPDumpBufferArrayIN,
+                  IMG_VOID * psBridgeOut, PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       IMG_UINT32 i;
+       PVR3DIF4_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+       IMG_UINT32 ui32BufferArrayLength =
+           psPDumpBufferArrayIN->ui32BufferArrayLength;
+       IMG_UINT32 ui32BufferArraySize =
+           ui32BufferArrayLength * sizeof(PVR3DIF4_KICKTA_DUMP_BUFFER);
+       PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+       PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+                                PVRSRV_BRIDGE_PDUMP_BUFFER_ARRAY);
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      ui32BufferArraySize,
+                      (IMG_PVOID *) & psKickTADumpBuffer, 0) != 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_PDUMP_BUFFER_ARRAY: "
+                                "PVRSRVLookupHandle failed (%d)", eError));
+                       break;
+               }
+               psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo;
+       }
+
+       if (eError == PVRSRV_OK) {
+               DumpBufferArray(psKickTADumpBuffer,
+                               ui32BufferArrayLength,
+                               psPDumpBufferArrayIN->bDumpPolls);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize,
+                 psKickTADumpBuffer, 0);
+
+       return 0;
+}
+
+static int
+PDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+                           PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *
+                           psPDump3DSignatureRegistersIN,
+                           IMG_VOID * psBridgeOut,
+                           PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       IMG_UINT32 ui32RegisterArraySize =
+           psPDump3DSignatureRegistersIN->ui32NumRegisters *
+           sizeof(IMG_UINT32);
+       IMG_UINT32 *pui32Registers = IMG_NULL;
+       int ret = -EFAULT;
+
+       PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+                                PVRSRV_BRIDGE_PDUMP_3D_SIGNATURE_REGISTERS);
+
+       if (ui32RegisterArraySize == 0) {
+               goto ExitNoError;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      ui32RegisterArraySize,
+                      (IMG_PVOID *) & pui32Registers, 0) != 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(psPDump3DSignatureRegistersIN->
+                                 ui32DumpFrameNum,
+                                 psPDump3DSignatureRegistersIN->bLastFrame,
+                                 pui32Registers,
+                                 psPDump3DSignatureRegistersIN->
+                                 ui32NumRegisters);
+
+ExitNoError:
+       ret = 0;
+Exit:
+       if (pui32Registers != IMG_NULL) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize,
+                         pui32Registers, 0);
+       }
+
+       return ret;
+}
+
+static int
+PDumpCounterRegistersBW(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;
+       int ret = -EFAULT;
+
+       PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+                                PVRSRV_BRIDGE_PDUMP_COUNTER_REGISTERS);
+
+       if (ui32RegisterArraySize == 0) {
+               goto ExitNoError;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      ui32RegisterArraySize,
+                      (IMG_PVOID *) & pui32Registers, 0) != 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(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 int
+PDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+                           PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *
+                           psPDumpTASignatureRegistersIN,
+                           IMG_VOID * psBridgeOut,
+                           PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       IMG_UINT32 ui32RegisterArraySize =
+           psPDumpTASignatureRegistersIN->ui32NumRegisters *
+           sizeof(IMG_UINT32);
+       IMG_UINT32 *pui32Registers = IMG_NULL;
+       int ret = -EFAULT;
+
+       PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+                                PVRSRV_BRIDGE_PDUMP_TA_SIGNATURE_REGISTERS);
+
+       if (ui32RegisterArraySize == 0) {
+               goto ExitNoError;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      ui32RegisterArraySize,
+                      (IMG_PVOID *) & pui32Registers, 0) != 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(psPDumpTASignatureRegistersIN->
+                                 ui32DumpFrameNum,
+                                 psPDumpTASignatureRegistersIN->
+                                 ui32TAKickCount,
+                                 psPDumpTASignatureRegistersIN->bLastFrame,
+                                 pui32Registers,
+                                 psPDumpTASignatureRegistersIN->
+                                 ui32NumRegisters);
+
+ExitNoError:
+       ret = 0;
+Exit:
+       if (pui32Registers != IMG_NULL) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize,
+                         pui32Registers, 0);
+       }
+
+       return ret;
+}
+#endif
+
+#if defined(SUPPORT_SGX)
+static 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 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 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.
+                             hCtlKernelMemInfoHandle,
+                             psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.
+                             hCtlKernelMemInfoHandle,
+                             PVRSRV_HANDLE_TYPE_MEM_INFO,
+                             PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+       return 0;
+}
+
+static 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;
+
+       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 (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;
+               }
+       }
+
+       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 =
+                   PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                      &psDoKickIN->sCCBKick.
+                                      ahTAStatusSyncInfo[i],
+                                      psDoKickIN->sCCBKick.
+                                      ahTAStatusSyncInfo[i],
+                                      PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               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 =
+                   PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                      &psDoKickIN->sCCBKick.
+                                      ah3DStatusSyncInfo[i],
+                                      psDoKickIN->sCCBKick.
+                                      ah3DStatusSyncInfo[i],
+                                      PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if (psRetOUT->eError != PVRSRV_OK) {
+                       return 0;
+               }
+       }
+
+       if (psDoKickIN->sCCBKick.hRenderSurfSyncInfo != IMG_NULL) {
+               psRetOUT->eError =
+                   PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                      &psDoKickIN->sCCBKick.
+                                      hRenderSurfSyncInfo,
+                                      psDoKickIN->sCCBKick.hRenderSurfSyncInfo,
+                                      PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+               if (psRetOUT->eError != PVRSRV_OK) {
+                       return 0;
+               }
+       }
+
+       psRetOUT->eError = SGXDoKickKM(hDevCookieInt, &psDoKickIN->sCCBKick);
+
+       return 0;
+}
+
+#if defined(TRANSFER_QUEUE)
+static 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);
+
+       return 0;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static 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 int
+SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+                PVRSRV_BRIDGE_IN_SGXGETMISCINFO * psSGXGetMiscInfoIN,
+                PVRSRV_BRIDGE_RETURN * psRetOUT,
+                PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+       SGX_MISC_INFO sMiscInfo;
+
+       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;
+       }
+
+       psDevInfo =
+           (PVRSRV_SGXDEV_INFO *) ((PVRSRV_DEVICE_NODE *) hDevCookieInt)->
+           pvDevice;
+
+       psRetOUT->eError = CopyFromUserWrapper(psPerProc,
+                                              ui32BridgeID,
+                                              &sMiscInfo,
+                                              psSGXGetMiscInfoIN->psMiscInfo,
+                                              sizeof(SGX_MISC_INFO));
+       if (psRetOUT->eError != PVRSRV_OK) {
+               return -EFAULT;
+       }
+#ifdef SUPPORT_SGX_HWPERF
+       if (sMiscInfo.eRequest == SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB) {
+               void *pAllocated;
+               IMG_HANDLE hAllocatedHandle;
+               void *psTmpUserData;
+               int allocatedSize;
+
+               allocatedSize =
+                   sMiscInfo.uData.sRetrieveCB.ui32ArraySize *
+                   sizeof(PVRSRV_SGX_HWPERF_CBDATA);
+
+               ASSIGN_AND_EXIT_ON_ERROR(psRetOUT->eError,
+                                        OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                                   allocatedSize,
+                                                   &pAllocated,
+                                                   &hAllocatedHandle));
+
+               psTmpUserData = sMiscInfo.uData.sRetrieveCB.psHWPerfData;
+               sMiscInfo.uData.sRetrieveCB.psHWPerfData = pAllocated;
+
+               psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo);
+               if (psRetOUT->eError != PVRSRV_OK) {
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 allocatedSize, pAllocated, hAllocatedHandle);
+                       return -EFAULT;
+               }
+
+               psRetOUT->eError = CopyToUserWrapper(psPerProc,
+                                                    ui32BridgeID,
+                                                    psTmpUserData,
+                                                    sMiscInfo.uData.
+                                                    sRetrieveCB.psHWPerfData,
+                                                    allocatedSize);
+
+               sMiscInfo.uData.sRetrieveCB.psHWPerfData = psTmpUserData;
+
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         allocatedSize, pAllocated, hAllocatedHandle);
+
+               if (psRetOUT->eError != PVRSRV_OK) {
+                       return -EFAULT;
+               }
+       } else
+#endif
+       {
+               psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo);
+               if (psRetOUT->eError != PVRSRV_OK) {
+                       return -EFAULT;
+               }
+       }
+
+       psRetOUT->eError = CopyToUserWrapper(psPerProc,
+                                            ui32BridgeID,
+                                            psSGXGetMiscInfoIN->psMiscInfo,
+                                            &sMiscInfo, sizeof(SGX_MISC_INFO));
+       if (psRetOUT->eError != PVRSRV_OK) {
+               return -EFAULT;
+       }
+       return 0;
+}
+
+#if defined(SUPPORT_SGX_HWPERF)
+static int
+SGXReadDiffCountersBW(IMG_UINT32 ui32BridgeID,
+                     PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS *
+                     psSGXReadDiffCountersIN,
+                     PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS *
+                     psSGXReadDiffCountersOUT,
+                     PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       IMG_HANDLE hDevCookieInt;
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+                                PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS);
+
+       psSGXReadDiffCountersOUT->eError =
+           PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+                              psSGXReadDiffCountersIN->hDevCookie,
+                              PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+       if (psSGXReadDiffCountersOUT->eError != PVRSRV_OK) {
+               return 0;
+       }
+
+       psSGXReadDiffCountersOUT->eError = SGXReadDiffCountersKM(hDevCookieInt,
+                                                                psSGXReadDiffCountersIN->
+                                                                ui32Reg,
+                                                                &psSGXReadDiffCountersOUT->
+                                                                ui32Old,
+                                                                psSGXReadDiffCountersIN->
+                                                                bNew,
+                                                                psSGXReadDiffCountersIN->
+                                                                ui32New,
+                                                                psSGXReadDiffCountersIN->
+                                                                ui32NewReset,
+                                                                psSGXReadDiffCountersIN->
+                                                                ui32CountersReg,
+                                                                &psSGXReadDiffCountersOUT->
+                                                                ui32Time,
+                                                                &psSGXReadDiffCountersOUT->
+                                                                bActive,
+                                                                &psSGXReadDiffCountersOUT->
+                                                                sDiffs);
+
+       return 0;
+}
+#endif
+
+static 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()
+           || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING)
+           || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN)) {
+               psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+               return 0;
+       }
+#if defined (__linux__)
+       PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+#endif
+       psPerProc->bInitProcess = IMG_TRUE;
+
+       psRetOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+static 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_GENERIC;
+               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,
+                                (IMG_BOOL) (((psRetOUT->eError == PVRSRV_OK)
+                                             && (psInitSrvDisconnectIN->
+                                                 bInitSuccesful))));
+
+       return 0;
+}
+
+static 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 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_NONE);
+
+       COMMIT_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc);
+
+       return 0;
+}
+
+static 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;
+}
+
+static 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_GENERIC;
+               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);
+       bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                   &hDummy,
+                                   psSGXDevInitPart2IN->sInitInfo.
+                                   hKernelCCBCtlMemInfo,
+                                   PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                   &hDummy,
+                                   psSGXDevInitPart2IN->sInitInfo.
+                                   hKernelCCBEventKickerMemInfo,
+                                   PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                   &hDummy,
+                                   psSGXDevInitPart2IN->sInitInfo.
+                                   hKernelSGXHostCtlMemInfo,
+                                   PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                   &hDummy,
+                                   psSGXDevInitPart2IN->sInitInfo.
+                                   hKernelHWProfilingMemInfo,
+                                   PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+       eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+                                   &hDummy,
+                                   psSGXDevInitPart2IN->sInitInfo.
+                                   hKernelHWPerfCBMemInfo,
+                                   PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+#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);
+               bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+       }
+
+       if (bLookupFailed) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevInitSGXPart2BW: A handle lookup failed"));
+               psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+               return 0;
+       }
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                             &psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelCCBMemInfo,
+                                             psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelCCBMemInfo,
+                                             PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bReleaseFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                             &psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelCCBCtlMemInfo,
+                                             psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelCCBCtlMemInfo,
+                                             PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bReleaseFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                             &psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelCCBEventKickerMemInfo,
+                                             psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelCCBEventKickerMemInfo,
+                                             PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bReleaseFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                             &psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelSGXHostCtlMemInfo,
+                                             psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelSGXHostCtlMemInfo,
+                                             PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bReleaseFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                             &psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelHWProfilingMemInfo,
+                                             psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelHWProfilingMemInfo,
+                                             PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bReleaseFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+       eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+                                             &psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelHWPerfCBMemInfo,
+                                             psSGXDevInitPart2IN->sInitInfo.
+                                             hKernelHWPerfCBMemInfo,
+                                             PVRSRV_HANDLE_TYPE_MEM_INFO);
+       bReleaseFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+#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);
+               bReleaseFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+       }
+
+       if (bReleaseFailed) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevInitSGXPart2BW: A handle release failed"));
+               psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+
+               PVR_DBG_BREAK;
+               return 0;
+       }
+
+       eError =
+           PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+                                       psSGXDevInitPart2IN->sInitInfo.
+                                       hKernelCCBMemInfo);
+       bDissociateFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError =
+           PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+                                       psSGXDevInitPart2IN->sInitInfo.
+                                       hKernelCCBCtlMemInfo);
+       bDissociateFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError =
+           PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+                                       psSGXDevInitPart2IN->sInitInfo.
+                                       hKernelCCBEventKickerMemInfo);
+       bDissociateFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+       eError =
+           PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+                                       psSGXDevInitPart2IN->sInitInfo.
+                                       hKernelSGXHostCtlMemInfo);
+       bDissociateFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+#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);
+       bDissociateFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+#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);
+               bDissociateFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+       }
+
+       if (bDissociateFailed) {
+               PVRSRVFreeDeviceMemKM(hDevCookieInt,
+                                     psSGXDevInitPart2IN->sInitInfo.
+                                     hKernelCCBMemInfo);
+               PVRSRVFreeDeviceMemKM(hDevCookieInt,
+                                     psSGXDevInitPart2IN->sInitInfo.
+                                     hKernelCCBCtlMemInfo);
+               PVRSRVFreeDeviceMemKM(hDevCookieInt,
+                                     psSGXDevInitPart2IN->sInitInfo.
+                                     hKernelSGXHostCtlMemInfo);
+
+               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_GENERIC;
+
+               PVR_DBG_BREAK;
+               return 0;
+       }
+
+       psRetOUT->eError =
+           DevInitSGXPart2KM(psPerProc,
+                             hDevCookieInt, &psSGXDevInitPart2IN->sInitInfo);
+
+       return 0;
+}
+
+static 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_GENERIC;
+               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 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 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_GENERIC;
+               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 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 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_GENERIC;
+               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 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 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 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);
+
+       return 0;
+}
+
+static 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 **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,
+                                 &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);
+
+       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 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 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;
+       IMG_UINT32 ui32KernelMemInfoHandlesCount =
+           psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+       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;
+       }
+
+       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;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+                      (IMG_VOID **) & phKernelMemInfoHandles,
+                      0) != PVRSRV_OK) {
+               ret = -ENOMEM;
+               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;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      ui32KernelMemInfoHandlesCount *
+                      sizeof(PVRSRV_KERNEL_MEM_INFO *),
+                      (IMG_VOID **) & ppsKernelMemInfos, 0) != PVRSRV_OK) {
+               ret = -ENOMEM;
+               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);
+
+       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,
+                                     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;
+}
+
+#endif
+
+static 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) {
+
+               ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+                                        OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                                   psGetMiscInfoOUT->sMiscInfo.
+                                                   ui32MemoryStrLen,
+                                                   (IMG_VOID **) &
+                                                   psGetMiscInfoOUT->sMiscInfo.
+                                                   pszMemoryStr, 0));
+
+               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 =
+                   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 (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);
+       }
+
+       return 0;
+}
+
+static int
+PVRSRVConnectBW(IMG_UINT32 ui32BridgeID,
+               IMG_VOID * psBridgeIn,
+               PVRSRV_BRIDGE_OUT_CONNECT_SERVICES * psConnectServicesOUT,
+               PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+       PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+       psConnectServicesOUT->hKernelServices = psPerProc->hPerProcData;
+       psConnectServicesOUT->eError = PVRSRV_OK;
+
+       return 0;
+}
+
+static 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 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 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 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 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 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 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 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 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;
+
+       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;
+       }
+
+       psCreateDispClassSwapChainOUT->eError =
+           PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+                                     psCreateDispClassSwapChainIN->ui32Flags,
+                                     &psCreateDispClassSwapChainIN->
+                                     sDstSurfAttrib,
+                                     &psCreateDispClassSwapChainIN->
+                                     sSrcSurfAttrib,
+                                     psCreateDispClassSwapChainIN->
+                                     ui32BufferCount,
+                                     psCreateDispClassSwapChainIN->
+                                     ui32OEMFlags, &hSwapChainInt,
+                                     &psCreateDispClassSwapChainOUT->
+                                     ui32SwapChainID);
+
+       if (psCreateDispClassSwapChainOUT->eError != PVRSRV_OK) {
+               return 0;
+       }
+
+       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 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 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 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 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);
+
+       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 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 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 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);
+
+       return 0;
+}
+
+static 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 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 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 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 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 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));
+
+       if (psKernelMemInfo->pvLinAddrKM) {
+               psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psKernelMemInfo->pvLinAddrKM;
+       } else {
+               psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psKernelMemInfo->sMemBlk.hOSMemHandle;
+       }
+       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 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 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_GENERIC;
+               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));
+
+       if (psKernelMemInfo->pvLinAddrKM) {
+               psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psKernelMemInfo->pvLinAddrKM;
+       } else {
+               psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+                   psKernelMemInfo->sMemBlk.hOSMemHandle;
+       }
+
+       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));
+               psMapMemInfoMemOUT->psKernelSyncInfo = IMG_NULL;
+       } 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 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 =
+           MMU_GetPDDevPAddr(BM_GetMMUContextFromMemContext
+                             (hDevMemContextInt));
+       if (psGetMmuPDDevPAddrOUT->sPDDevPAddr.uiAddr) {
+               psGetMmuPDDevPAddrOUT->eError = PVRSRV_OK;
+       } else {
+               psGetMmuPDDevPAddrOUT->eError = PVRSRV_ERROR_GENERIC;
+       }
+       return 0;
+}
+
+static 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 %lu (%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 %lu mapped to "
+                "Dummy Wrapper (probably not what you want!)",
+                __FUNCTION__, ui32BridgeID));
+#endif
+       return -ENOTTY;
+}
+
+#define SetDispatchTableEntry(ui32Index, pfFunction) \
+       _SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+static IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+                      const IMG_CHAR * pszIOCName,
+                      BridgeWrapperFunction pfFunction,
+                      const IMG_CHAR * pszFunctionName)
+{
+       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=%lu)",
+                        __FUNCTION__, pszIOCName, ui32Index));
+#endif
+               PVR_DPF((PVR_DBG_ERROR,
+                        "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+                        __FUNCTION__));
+       }
+
+       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 %lu (%s) and %lu (%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 %lu and %lu (%s)",
+                        __FUNCTION__, ui32PrevIndex, ui32Index, pszIOCName));
+#endif
+               PVR_DPF((PVR_DBG_ERROR,
+                        "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+                        __FUNCTION__));
+       }
+
+       g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+#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;
+}
+
+PVRSRV_ERROR CommonBridgeInit(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DEVICES,
+                             PVRSRVEnumerateDevicesBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO,
+                             PVRSRVAcquireDeviceDataBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_DEVICEINFO, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT,
+                             PVRSRVCreateDeviceMemContextBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT,
+                             PVRSRVDestroyDeviceMemContextBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO,
+                             PVRSRVGetDeviceMemHeapInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_DEVICEMEM,
+                             PVRSRVAllocDeviceMemBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEVICEMEM,
+                             PVRSRVFreeDeviceMemBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GETFREE_DEVICEMEM,
+                             PVRSRVGetFreeDeviceMemBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_COMMANDQUEUE, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_KV_TO_MMAP_DATA,
+                             PVRMMapKVIndexAddressToMMapDataBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_CONNECT_SERVICES, PVRSRVConnectBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_DISCONNECT_SERVICES,
+                             PVRSRVDisconnectBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_DEVICE_MEM, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVICEMEMINFO, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEV_VIRTMEM, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_EXT_MEMORY, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_EXT_MEMORY, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY,
+                             PVRSRVMapDeviceMemoryBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEV_MEMORY,
+                             PVRSRVUnmapDeviceMemoryBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY,
+                             PVRSRVMapDeviceClassMemoryBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY,
+                             PVRSRVUnmapDeviceClassMemoryBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER, DummyBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP, DummyBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_FB_STATS, DummyBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_MISC_INFO, PVRSRVGetMiscInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MISC_INFO, DummyBW);
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+       SetDispatchTableEntry(PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES, DummyBW);
+#endif
+
+#if defined(PDUMP)
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_INIT, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPOL, PDumpMemPolBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPMEM, PDumpMemBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REG, PDumpRegWithFlagsBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REGPOL, PDumpRegPolBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_COMMENT, PDumpCommentBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SETFRAME, PDumpSetFrameBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_ISCAPTURING,
+                             PDumpIsCaptureFrameBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPBITMAP, PDumpBitmapBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPREADREG, PDumpReadRegBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SYNCPOL, PDumpSyncPolBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPSYNC, PDumpSyncDumpBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DRIVERINFO,
+                             PDumpDriverInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PDREG, PDumpPDRegBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR,
+                             PDumpPDDevPAddrBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_BUFFER_ARRAY,
+                             PDumpBufferArrayBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ,
+                             PDumpCycleCountRegReadBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_3D_SIGNATURE_REGISTERS,
+                             PDump3DSignatureRegistersBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_COUNTER_REGISTERS,
+                             PDumpCounterRegistersBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_TA_SIGNATURE_REGISTERS,
+                             PDumpTASignatureRegistersBW);
+#endif
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_OEMJTABLE, DummyBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, PVRSRVEnumerateDCBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE,
+                             PVRSRVOpenDCDeviceBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE,
+                             PVRSRVCloseDCDeviceBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS,
+                             PVRSRVEnumDCFormatsBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS,
+                             PVRSRVEnumDCDimsBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER,
+                             PVRSRVGetDCSystemBufferBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_INFO,
+                             PVRSRVGetDCInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN,
+                             PVRSRVCreateDCSwapChainBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN,
+                             PVRSRVDestroyDCSwapChainBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT,
+                             PVRSRVSetDCDstRectBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT,
+                             PVRSRVSetDCSrcRectBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY,
+                             PVRSRVSetDCDstColourKeyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY,
+                             PVRSRVSetDCSrcColourKeyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS,
+                             PVRSRVGetDCBuffersBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER,
+                             PVRSRVSwapToDCBufferBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM,
+                             PVRSRVSwapToDCSystemBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE,
+                             PVRSRVOpenBCDeviceBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE,
+                             PVRSRVCloseBCDeviceBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO,
+                             PVRSRVGetBCInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER,
+                             PVRSRVGetBCBufferBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_EXT_MEMORY,
+                             PVRSRVWrapExtMemoryBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY,
+                             PVRSRVUnwrapExtMemoryBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM,
+                             PVRSRVAllocSharedSysMemoryBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM,
+                             PVRSRVFreeSharedSysMemoryBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEMINFO_MEM,
+                             PVRSRVMapMemInfoMemBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR,
+                             MMU_GetPDDevPAddrBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_CONNECT,
+                             PVRSRVInitSrvConnectBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_DISCONNECT,
+                             PVRSRVInitSrvDisconnectBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_WAIT,
+                             PVRSRVEventObjectWaitBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_OPEN,
+                             PVRSRVEventObjectOpenBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE,
+                             PVRSRVEventObjectCloseBW);
+
+#if defined(SUPPORT_SGX)
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETCLIENTINFO,
+                             SGXGetClientInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO,
+                             SGXReleaseClientInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO,
+                             SGXGetInternalDevInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DOKICK, SGXDoKickBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READREGISTRYDWORD, DummyBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SCHEDULECOMMAND, DummyBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE,
+                             SGX2DQueryBlitsCompleteBW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMMUPDADDR, DummyBW);
+
+#if defined(TRANSFER_QUEUE)
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMITTRANSFER,
+                             SGXSubmitTransferBW);
+#endif
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMISCINFO, SGXGetMiscInfoBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT,
+                             SGXGetInfoForSrvinitBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DEVINITPART2,
+                             SGXDevInitPart2BW);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC,
+                             SGXFindSharedPBDescBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC,
+                             SGXUnrefSharedPBDescBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC,
+                             SGXAddSharedPBDescBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT,
+                             SGXRegisterHWRenderContextBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET,
+                             SGXFlushHWRenderTargetBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT,
+                             SGXUnregisterHWRenderContextBW);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#if defined(TRANSFER_QUEUE)
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMIT2D, SGXSubmit2DBW);
+#endif
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT,
+                             SGXRegisterHW2DContextBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT,
+                             SGXUnregisterHW2DContextBW);
+#endif
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT,
+                             SGXRegisterHWTransferContextBW);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT,
+                             SGXUnregisterHWTransferContextBW);
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS,
+                             SGXReadDiffCountersBW);
+#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;
+}
+
+int BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+                     PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
+{
+
+       IMG_VOID *psBridgeIn;
+       IMG_VOID *psBridgeOut;
+       BridgeWrapperFunction pfBridgeHandler;
+       IMG_UINT32 ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+       int err = -EFAULT;
+
+#if defined(DEBUG_TRACE_BRIDGE_KM)
+       PVR_DPF((PVR_DBG_ERROR, "%s: %s",
+                __FUNCTION__, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+       g_BridgeDispatchTable[ui32BridgeID].ui32CallCount++;
+       g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+       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;
+
+               if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+                       goto return_fault;
+               }
+
+               psBridgeIn =
+                   ((ENV_DATA *) psSysData->pvEnvSpecificData)->pvBridgeData;
+               psBridgeOut =
+                   (IMG_PVOID) ((IMG_PBYTE) psBridgeIn +
+                                PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+               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) g_BridgeDispatchTable[ui32BridgeID].
+           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;
+return_fault:
+       ReleaseHandleBatch(psPerProc);
+       return err;
+}
diff --git a/pvr/bridged_pvr_bridge.h b/pvr/bridged_pvr_bridge.h
new file mode 100644 (file)
index 0000000..c0130c5
--- /dev/null
@@ -0,0 +1,86 @@
+/**********************************************************************
+ *
+ * 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
+
+       typedef 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;
+#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_SGX)
+#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+#else
+#error "FIXME: BRIDGE_DISPATCH_TABLE_ENTRY_COUNT unset"
+#endif
+
+       extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+           g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#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);
+
+       int BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+                             PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/buffer_manager.c b/pvr/buffer_manager.c
new file mode 100644 (file)
index 0000000..d293915
--- /dev/null
@@ -0,0 +1,1574 @@
+/**********************************************************************
+ *
+ * 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"
+
+#define MIN(a,b)       (a > b ? b : a)
+
+static IMG_BOOL
+ZeroBuf(BM_BUF * pBuf, BM_MAPPING * pMapping, IMG_UINT32 ui32Bytes,
+       IMG_UINT32 ui32Flags);
+static void BM_FreeMemory(void *pH, IMG_UINTPTR_T base, BM_MAPPING * psMapping);
+static IMG_BOOL
+BM_ImportMemory(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 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 (pBMContext=%08X, uSize=0x%x, uFlags=0x%x, align=0x%x, pBuf=%08X)",
+                pBMContext, uSize, uFlags, uDevVAddrAlignment, pBuf));
+
+       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;
+               } else {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "AllocMemory: backing store type doesn't match heap"));
+                       return IMG_FALSE;
+               }
+
+               if (!RA_Alloc(pArena,
+                             uSize,
+                             IMG_NULL,
+                             (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 =
+                           (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 = pMapping->CpuPAddr;
+
+               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);
+
+                       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) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "AllocMemory: OSAllocMem(0x%x) FAILED"));
+                       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->pBMHeap = psBMHeap;
+       pBuf->pMapping = pMapping;
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "AllocMemory: pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+                pMapping,
+                pMapping->DevVAddr.uiAddr,
+                pMapping->CpuVAddr,
+                pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "AllocMemory: pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+                pBuf,
+                pBuf->DevVAddr.uiAddr,
+                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_UINT32 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_UINT32 const ui32PageSize = HOST_PAGESIZE();
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, bPhysContig=0x%x, pvCPUVAddr = 0x%x, flags=0x%x, pBuf=%08X)",
+                psBMHeap, uSize, ui32BaseOffset, bPhysContig, pvCPUVAddr,
+                uFlags, pBuf));
+
+       PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
+
+       PVR_ASSERT(((IMG_UINT32) pvCPUVAddr & (ui32PageSize - 1)) == 0);
+
+       uSize += ui32BaseOffset;
+       uSize = HOST_PAGEALIGN(uSize);
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(*pMapping),
+                      (IMG_PVOID *) & pMapping, IMG_NULL) != 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;
+
+       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, CpuVAddr = 0x%08X, Size=%d) failed",
+                                        pMapping->CpuPAddr, pMapping->CpuVAddr,
+                                        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 CpuVAddr = 0x%08X, Size=%d) failed",
+                                        pMapping->CpuVAddr, 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, 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,
+                                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 =
+                   (void *)((IMG_UINTPTR_T) pMapping->CpuVAddr +
+                            ui32BaseOffset);
+       }
+       pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + 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: pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+                pMapping, pMapping->DevVAddr.uiAddr,
+                pMapping->CpuVAddr, pMapping->CpuPAddr.uiAddr,
+                pMapping->uSize));
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "WrapMemory: pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+                pBuf, pBuf->DevVAddr.uiAddr, pBuf->CpuVAddr,
+                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_UINT32 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_UINT32 ui32BytesRemaining = ui32Bytes;
+               IMG_UINT32 ui32CurrentOffset = 0;
+               IMG_CPU_PHYADDR CpuPAddr;
+
+               PVR_ASSERT(pBuf->hOSMemHandle);
+
+               while (ui32BytesRemaining > 0) {
+                       IMG_UINT32 ui32BlockBytes =
+                           MIN(ui32BytesRemaining, HOST_PAGESIZE());
+                       CpuPAddr =
+                           OSMemHandleToCpuPAddr(pBuf->hOSMemHandle,
+                                                 ui32CurrentOffset);
+
+                       if (CpuPAddr.uiAddr & (HOST_PAGESIZE() - 1)) {
+                               ui32BlockBytes =
+                                   MIN(ui32BytesRemaining,
+                                       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 void FreeBuf(BM_BUF * pBuf, IMG_UINT32 ui32Flags)
+{
+       BM_MAPPING *pMapping;
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "FreeBuf: pBuf=%08X: DevVAddr=%08X CpuVAddr=%08X CpuPAddr=%08X",
+                pBuf, pBuf->DevVAddr.uiAddr, pBuf->CpuVAddr,
+                pBuf->CpuPAddr.uiAddr));
+
+       pMapping = pBuf->pMapping;
+
+       if (ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) {
+
+               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);
+               }
+       } else {
+
+               if (pBuf->hOSMemHandle != pMapping->hOSMemHandle) {
+                       OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
+               }
+               if (ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) {
+
+                       RA_Free(pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr,
+                               IMG_FALSE);
+               } else {
+                       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;
+                       }
+
+                       DevMemoryFree(pMapping);
+
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING),
+                                 pMapping, IMG_NULL);
+               }
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
+}
+
+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 = 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(IMG_PVOID pvParam,
+                                             IMG_UINT32 ui32Param)
+{
+       BM_CONTEXT *pBMContext = pvParam;
+       BM_CONTEXT **ppBMContext;
+       BM_HEAP *psBMHeap, *psTmpBMHeap;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       psDeviceNode = pBMContext->psDeviceNode;
+
+       psBMHeap = pBMContext->psBMHeap;
+       while (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_DestroyContext: backing store type unsupported"));
+                       return PVRSRV_ERROR_GENERIC;
+               }
+
+               psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+               psTmpBMHeap = psBMHeap;
+
+               psBMHeap = psBMHeap->psNext;
+
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psTmpBMHeap, IMG_NULL);
+       }
+
+       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 {
+
+               for (ppBMContext = &psDeviceNode->sDevMemoryInfo.pBMContext;
+                    *ppBMContext; ppBMContext = &((*ppBMContext)->psNext)) {
+                       if (*ppBMContext == pBMContext) {
+
+                               *ppBMContext = pBMContext->psNext;
+
+                               break;
+                       }
+               }
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pBMContext, IMG_NULL);
+
+       return PVRSRV_OK;
+}
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE * psDeviceNode,
+                IMG_DEV_PHYADDR * psPDDevPAddr,
+                PVRSRV_PER_PROCESS_DATA * psPerProc, IMG_BOOL * pbCreated)
+{
+       BM_CONTEXT *pBMContext;
+       BM_HEAP *psBMHeap;
+       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) {
+               for (pBMContext = psDevMemoryInfo->pBMContext;
+                    pBMContext != IMG_NULL; pBMContext = pBMContext->psNext) {
+                       if (ResManFindResourceByPtr
+                           (hResManContext,
+                            pBMContext->hResItem) == PVRSRV_OK) {
+
+                               pBMContext->ui32RefCount++;
+
+                               return (IMG_HANDLE) pBMContext;
+                       }
+               }
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(struct _BM_CONTEXT_),
+                      (IMG_PVOID *) & pBMContext, IMG_NULL) != 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);
+               PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
+
+               pBMContext->psBMSharedHeap =
+                   psDevMemoryInfo->pBMKernelContext->psBMHeap;
+
+               psBMHeap = pBMContext->psBMSharedHeap;
+               while (psBMHeap) {
+                       switch (psBMHeap->sDevArena.DevMemHeapType) {
+                       case DEVICE_MEMORY_HEAP_SHARED:
+                       case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+                               {
+
+                                       psDeviceNode->
+                                           pfnMMUInsertHeap(pBMContext->
+                                                            psMMUContext,
+                                                            psBMHeap->
+                                                            pMMUHeap);
+                                       break;
+                               }
+                       }
+
+                       psBMHeap = psBMHeap->psNext;
+               }
+
+               pBMContext->psNext = psDevMemoryInfo->pBMContext;
+               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:
+       BM_DestroyContextCallBack(pBMContext, 0);
+
+       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 = pBMContext->psDeviceNode;
+       BM_HEAP *psBMHeap;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap"));
+
+       if (!pBMContext) {
+               return IMG_NULL;
+       }
+
+       if (pBMContext->ui32RefCount > 0) {
+               psBMHeap = pBMContext->psBMHeap;
+
+               while (psBMHeap) {
+                       if (psBMHeap->sDevArena.ui32HeapID ==
+                           psDevMemHeapInfo->ui32HeapID)
+                       {
+
+                               return psBMHeap;
+                       }
+                       psBMHeap = psBMHeap->psNext;
+               }
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(BM_HEAP),
+                      (IMG_PVOID *) & psBMHeap, IMG_NULL) != 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.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
+       psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+
+       psBMHeap->pBMContext = pBMContext;
+
+       psBMHeap->pMMUHeap =
+           psDeviceNode->pfnMMUCreate(pBMContext->psMMUContext,
+                                      &psBMHeap->sDevArena,
+                                      &psBMHeap->pVMArena);
+       if (!psBMHeap->pMMUHeap) {
+               PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed"));
+               goto ErrorExit;
+       }
+
+       psBMHeap->pImportArena = RA_Create(psDevMemHeapInfo->pszBSName,
+                                          0, 0, IMG_NULL,
+                                          HOST_PAGESIZE(),
+                                          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;
+               }
+       }
+
+       psBMHeap->psNext = pBMContext->psBMHeap;
+       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, 0, 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) {
+               BM_HEAP **ppsBMHeap;
+
+               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);
+
+               ppsBMHeap = &psBMHeap->pBMContext->psBMHeap;
+               while (*ppsBMHeap) {
+                       if (*ppsBMHeap == psBMHeap) {
+
+                               *ppsBMHeap = psBMHeap->psNext;
+                               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBMHeap,
+                                         IMG_NULL);
+                               break;
+                       }
+                       ppsBMHeap = &((*ppsBMHeap)->psNext);
+               }
+       } 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 = 0;
+
+       if (pui32Flags) {
+               uFlags = *pui32Flags;
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)",
+                uSize, uFlags, uDevVAddrAlignment));
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               return IMG_FALSE;
+       }
+
+       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) != 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)=%08X",
+                uSize, uFlags, pBuf));
+
+       pBuf->ui32RefCount = 1;
+       *phBuf = (BM_HANDLE) pBuf;
+       *pui32Flags = uFlags | psBMHeap->ui32Attribs;
+
+       return IMG_TRUE;
+}
+
+IMG_BOOL
+BM_Wrap(IMG_HANDLE hDevMemHeap,
+       IMG_UINT32 ui32Size,
+       IMG_UINT32 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)
+               uFlags |= *pui32Flags;
+
+       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, pvCPUVAddr, uFlags));
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK)
+               return IMG_FALSE;
+
+       sHashAddress = psSysAddr[0];
+
+       sHashAddress.uiAddr += ui32Offset;
+
+       pBuf =
+           (BM_BUF *) HASH_Retrieve(psBMContext->pBufferHash,
+                                    (IMG_UINTPTR_T) sHashAddress.uiAddr);
+
+       if (pBuf) {
+               IMG_UINT32 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) != 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,
+                    (IMG_UINTPTR_T) sHashAddress.uiAddr,
+                    (IMG_UINTPTR_T) pBuf)) {
+                       FreeBuf(pBuf, uFlags);
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf,
+                                 IMG_NULL);
+                       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)=%08X(devVAddr=%08X)",
+                ui32Size, uFlags, pBuf, pBuf->DevVAddr.uiAddr));
+
+       pBuf->ui32RefCount = 1;
+       *phBuf = (BM_HANDLE) pBuf;
+       if (pui32Flags)
+               *pui32Flags = uFlags;
+
+       return IMG_TRUE;
+}
+
+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=%08X)", hBuf));
+       PVR_ASSERT(pBuf != IMG_NULL);
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK)
+               return;
+
+       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_CPU_VIRTADDR BM_HandleToCpuVaddr(BM_HANDLE hBuf)
+{
+       BM_BUF *pBuf = (BM_BUF *) hBuf;
+
+       PVR_ASSERT(pBuf != IMG_NULL);
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "BM_HandleToCpuVaddr(h=%08X)=%08X", hBuf, pBuf->CpuVAddr));
+       return pBuf->CpuVAddr;
+}
+
+IMG_DEV_VIRTADDR BM_HandleToDevVaddr(BM_HANDLE hBuf)
+{
+       BM_BUF *pBuf = (BM_BUF *) hBuf;
+
+       PVR_ASSERT(pBuf != IMG_NULL);
+       PVR_DPF((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=%08X)=%08X", hBuf,
+                pBuf->DevVAddr));
+       return pBuf->DevVAddr;
+}
+
+IMG_SYS_PHYADDR BM_HandleToSysPaddr(BM_HANDLE hBuf)
+{
+       BM_BUF *pBuf = (BM_BUF *) hBuf;
+
+       PVR_ASSERT(pBuf != IMG_NULL);
+       PVR_DPF((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=%08X)=%08X", 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);
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "BM_HandleToOSMemHandle(h=%08X)=%08X",
+                hBuf, pBuf->hOSMemHandle));
+       return pBuf->hOSMemHandle;
+}
+
+IMG_BOOL
+BM_ContiguousStatistics(IMG_UINT32 uFlags,
+                       IMG_UINT32 * pTotalBytes, IMG_UINT32 * pAvailableBytes)
+{
+       if (pAvailableBytes || pTotalBytes || uFlags) ;
+       return IMG_FALSE;
+}
+
+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 = HOST_PAGESIZE();
+       }
+#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
+
+       PDUMPMALLOCPAGES(psDeviceNode->sDevId.eDeviceType,
+                        pMapping->DevVAddr.uiAddr, pMapping->CpuVAddr,
+                        pMapping->hOSMemHandle, ui32PDumpSize,
+                        (IMG_HANDLE) pMapping);
+
+       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 void DevMemoryFree(BM_MAPPING * pMapping)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+       IMG_UINT32 ui32PSize;
+#endif
+
+#ifdef PDUMP
+
+       if (pMapping->ui32Flags & PVRSRV_MEM_DUMMY) {
+
+               ui32PSize = HOST_PAGESIZE();
+       } else {
+               ui32PSize = pMapping->uSize;
+       }
+
+       PDUMPFREEPAGES(pMapping->pBMHeap, pMapping->DevVAddr,
+                      ui32PSize, (IMG_HANDLE) pMapping,
+                      (IMG_BOOL) (pMapping->
+                                  ui32Flags & PVRSRV_MEM_INTERLEAVED));
+#endif
+
+       psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+       psDeviceNode->pfnMMUFree(pMapping->pBMHeap->pMMUHeap,
+                                pMapping->DevVAddr, pMapping->uSize);
+}
+
+static IMG_BOOL
+BM_ImportMemory(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=%08X, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
+                pBMContext, uRequestSize, uFlags, uDevVAddrAlignment));
+
+       PVR_ASSERT(ppsMapping != IMG_NULL);
+       PVR_ASSERT(pBMContext != IMG_NULL);
+
+       uSize = HOST_PAGEALIGN(uRequestSize);
+       PVR_ASSERT(uSize >= uRequestSize);
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(BM_MAPPING),
+                      (IMG_PVOID *) & pMapping, IMG_NULL) != 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;
+
+       if (pActualSize) {
+               *pActualSize = uSize;
+       }
+
+       if (pMapping->ui32Flags & PVRSRV_MEM_DUMMY) {
+               uPSize = HOST_PAGESIZE();
+       } else {
+               uPSize = pMapping->uSize;
+       }
+
+       if (pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) {
+
+               if (OSAllocPages(pBMHeap->ui32Attribs,
+                                uPSize,
+                                (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;
+
+               PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
+
+               if (!RA_Alloc(pBMHeap->pLocalDevMemArena,
+                             uPSize,
+                             IMG_NULL,
+                             IMG_NULL,
+                             0,
+                             HOST_PAGESIZE(),
+                             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,
+                                 pBMHeap->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 = HOST_PAGESIZE();
+               } else {
+                       uPSize = pMapping->uSize;
+               }
+
+               if (pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) {
+                       OSFreePages(pBMHeap->ui32Attribs,
+                                   uPSize,
+                                   (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 void BM_FreeMemory(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=%08X, base=0x%x, psMapping=0x%x)", h, _base,
+                psMapping));
+
+       PVR_ASSERT(psMapping != IMG_NULL);
+
+       DevMemoryFree(psMapping);
+
+       if ((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0) {
+               psMapping->uSize /= 2;
+       }
+
+       if (psMapping->ui32Flags & PVRSRV_MEM_DUMMY) {
+               uPSize = HOST_PAGESIZE();
+       } else {
+               uPSize = psMapping->uSize;
+       }
+
+       if (pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) {
+               OSFreePages(pBMHeap->ui32Attribs,
+                           uPSize,
+                           (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=%08X, base=0x%x, psMapping=0x%x)",
+                h, _base, psMapping));
+}
+
+PVRSRV_ERROR 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"));
+
+       if (!psMemInfo || !psDevPAddr) {
+               PVR_DPF((PVR_DBG_ERROR, "BM_GetPhysPageAddr: Invalid params"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       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);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BM_GetHeapInfo(IMG_HANDLE hDevMemHeap,
+                           PVRSRV_HEAP_INFO * psHeapInfo)
+{
+       BM_HEAP *psBMHeap = (BM_HEAP *) hDevMemHeap;
+
+       PVR_DPF((PVR_DBG_VERBOSE, "BM_GetHeapInfo"));
+
+       psHeapInfo->hDevMemHeap = hDevMemHeap;
+       psHeapInfo->sDevVAddrBase = psBMHeap->sDevArena.BaseDevVAddr;
+       psHeapInfo->ui32HeapByteSize = psBMHeap->sDevArena.ui32Size;
+       psHeapInfo->ui32Attribs = psBMHeap->ui32Attribs;
+
+       return PVRSRV_OK;
+}
+
+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/pvr/buffer_manager.h b/pvr/buffer_manager.h
new file mode 100644 (file)
index 0000000..1523bce
--- /dev/null
@@ -0,0 +1,180 @@
+/**********************************************************************
+ *
+ * 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;
+
+               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;
+       } 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;
+
+               struct _BM_HEAP_ *psNext;
+       };
+
+       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;
+       };
+
+       typedef 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_UINT32 ui32Size,
+                   IMG_UINT32 ui32Offset,
+                   IMG_BOOL bPhysContig,
+                   IMG_SYS_PHYADDR * psSysAddr,
+                   IMG_VOID * pvCPUVAddr,
+                   IMG_UINT32 * pui32Flags, BM_HANDLE * phBuf);
+
+       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_BOOL
+           BM_ContiguousStatistics(IMG_UINT32 uFlags,
+                                   IMG_UINT32 * pTotalBytes,
+                                   IMG_UINT32 * pAvailableBytes);
+
+       PVRSRV_ERROR BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO * psMemInfo,
+                                       IMG_DEV_VIRTADDR sDevVPageAddr,
+                                       IMG_DEV_PHYADDR * psDevPAddr);
+
+       PVRSRV_ERROR BM_GetHeapInfo(IMG_HANDLE hDevMemHeap,
+                                   PVRSRV_HEAP_INFO * psHeapInfo);
+
+       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);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/bufferclass_example.c b/pvr/bufferclass_example.c
new file mode 100644 (file)
index 0000000..83cb59a
--- /dev/null
@@ -0,0 +1,284 @@
+/**********************************************************************
+ *
+ * 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 "bufferclass_example.h"
+
+static IMG_VOID *gpvAnchor = IMG_NULL;
+static PFN_BC_GET_PVRJTABLE pfnGetPVRJTable = IMG_NULL;
+
+BC_EXAMPLE_DEVINFO *GetAnchorPtr(IMG_VOID)
+{
+       return (BC_EXAMPLE_DEVINFO *) gpvAnchor;
+}
+
+static IMG_VOID SetAnchorPtr(BC_EXAMPLE_DEVINFO * psDevInfo)
+{
+       gpvAnchor = (IMG_VOID *) psDevInfo;
+}
+
+static PVRSRV_ERROR OpenBCDevice(IMG_HANDLE * phDevice)
+{
+       BC_EXAMPLE_DEVINFO *psDevInfo;
+
+       psDevInfo = GetAnchorPtr();
+
+       *phDevice = (IMG_HANDLE) psDevInfo;
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR CloseBCDevice(IMG_HANDLE hDevice)
+{
+       PVR_UNREFERENCED_PARAMETER(hDevice);
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetBCBuffer(IMG_HANDLE hDevice,
+                               IMG_UINT32 ui32BufferNumber,
+                               PVRSRV_SYNC_DATA * psSyncData,
+                               IMG_HANDLE * phBuffer)
+{
+       BC_EXAMPLE_DEVINFO *psDevInfo;
+
+       if (!hDevice || !phBuffer) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (BC_EXAMPLE_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_EXAMPLE_DEVINFO *psDevInfo;
+
+       if (!hDevice || !psBCInfo) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (BC_EXAMPLE_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)
+{
+       BC_EXAMPLE_BUFFER *psBuffer;
+
+       if (!hDevice || !hBuffer || !ppsSysAddr || !pui32ByteSize) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psBuffer = (BC_EXAMPLE_BUFFER *) hBuffer;
+
+       *ppsSysAddr = &psBuffer->sPageAlignSysAddr;
+       *ppvCpuVAddr = psBuffer->sCPUVAddr;
+
+       *pui32ByteSize = psBuffer->ui32Size;
+
+       *phOSMapInfo = IMG_NULL;
+       *pbIsContiguous = IMG_TRUE;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BC_Example_Init(IMG_VOID)
+{
+       BC_EXAMPLE_DEVINFO *psDevInfo;
+       IMG_CPU_PHYADDR sSystemBufferCPUPAddr;
+       IMG_UINT32 i;
+
+       psDevInfo = GetAnchorPtr();
+
+       if (psDevInfo == IMG_NULL) {
+
+               psDevInfo =
+                   (BC_EXAMPLE_DEVINFO *)
+                   BCAllocKernelMem(sizeof(BC_EXAMPLE_DEVINFO));
+
+               if (!psDevInfo) {
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+
+               SetAnchorPtr((IMG_VOID *) psDevInfo);
+
+               psDevInfo->ui32RefCount = 0;
+
+               if (BCOpenPVRServices(&psDevInfo->hPVRServices) != PVRSRV_OK) {
+                       return PVRSRV_ERROR_INIT_FAILURE;
+               }
+               if (BCGetLibFuncAddr
+                   (psDevInfo->hPVRServices, "PVRGetBufferClassJTable",
+                    &pfnGetPVRJTable) != PVRSRV_OK) {
+                       return PVRSRV_ERROR_INIT_FAILURE;
+               }
+
+               if (!(*pfnGetPVRJTable) (&psDevInfo->sPVRJTable)) {
+                       return PVRSRV_ERROR_INIT_FAILURE;
+               }
+
+               psDevInfo->ui32NumBuffers = 0;
+
+               psDevInfo->psSystemBuffer =
+                   BCAllocKernelMem(sizeof(BC_EXAMPLE_BUFFER) *
+                                    BC_EXAMPLE_NUM_BUFFERS);
+
+               if (!psDevInfo->psSystemBuffer) {
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+
+               psDevInfo->sBufferInfo.pixelformat = BC_EXAMPLE_PIXELFORMAT;
+               psDevInfo->sBufferInfo.ui32Width = BC_EXAMPLE_WIDTH;
+               psDevInfo->sBufferInfo.ui32Height = BC_EXAMPLE_HEIGHT;
+               psDevInfo->sBufferInfo.ui32ByteStride = BC_EXAMPLE_STRIDE;
+               psDevInfo->sBufferInfo.ui32BufferDeviceID = BC_EXAMPLE_DEVICEID;
+               psDevInfo->sBufferInfo.ui32Flags =
+                   PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE |
+                   PVRSRV_BC_FLAGS_YUVCSC_BT601;
+
+               for (i = 0; i < BC_EXAMPLE_NUM_BUFFERS; i++) {
+                       IMG_UINT32 ui32Size =
+                           BC_EXAMPLE_HEIGHT * BC_EXAMPLE_STRIDE;
+
+                       if (psDevInfo->sBufferInfo.pixelformat ==
+                           PVRSRV_PIXEL_FORMAT_NV12) {
+
+                               ui32Size +=
+                                   ((BC_EXAMPLE_STRIDE >> 1) *
+                                    (BC_EXAMPLE_HEIGHT >> 1) << 1);
+                       }
+
+                       if (BCAllocContigMemory(ui32Size,
+                                               &psDevInfo->psSystemBuffer[i].
+                                               hMemHandle,
+                                               &psDevInfo->psSystemBuffer[i].
+                                               sCPUVAddr,
+                                               &sSystemBufferCPUPAddr) !=
+                           PVRSRV_OK) {
+                               break;
+                       }
+
+                       psDevInfo->ui32NumBuffers++;
+
+                       psDevInfo->psSystemBuffer[i].ui32Size = ui32Size;
+                       psDevInfo->psSystemBuffer[i].sSysAddr =
+                           CpuPAddrToSysPAddrBC(sSystemBufferCPUPAddr);
+                       psDevInfo->psSystemBuffer[i].sPageAlignSysAddr.uiAddr =
+                           (psDevInfo->psSystemBuffer[i].sSysAddr.
+                            uiAddr & 0xFFFFF000);
+                       psDevInfo->psSystemBuffer[i].psSyncData = IMG_NULL;
+               }
+
+               psDevInfo->sBufferInfo.ui32BufferCount =
+                   psDevInfo->ui32NumBuffers;
+
+               psDevInfo->sBCJTable.ui32TableSize =
+                   sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE);
+               psDevInfo->sBCJTable.pfnOpenBCDevice = OpenBCDevice;
+               psDevInfo->sBCJTable.pfnCloseBCDevice = CloseBCDevice;
+               psDevInfo->sBCJTable.pfnGetBCBuffer = GetBCBuffer;
+               psDevInfo->sBCJTable.pfnGetBCInfo = GetBCInfo;
+               psDevInfo->sBCJTable.pfnGetBufferAddr = GetBCBufferAddr;
+
+               if (psDevInfo->sPVRJTable.
+                   pfnPVRSRVRegisterBCDevice(&psDevInfo->sBCJTable,
+                                             &psDevInfo->ui32DeviceID) !=
+                   PVRSRV_OK) {
+                       return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
+               }
+       }
+
+       psDevInfo->ui32RefCount++;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BC_Example_Deinit(IMG_VOID)
+{
+       BC_EXAMPLE_DEVINFO *psDevInfo;
+       IMG_UINT32 i;
+       psDevInfo = GetAnchorPtr();
+
+       if (psDevInfo == IMG_NULL) {
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       psDevInfo->ui32RefCount--;
+
+       if (psDevInfo->ui32RefCount == 0) {
+
+               PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable =
+                   &psDevInfo->sPVRJTable;
+
+               if (psJTable->
+                   pfnPVRSRVRemoveBCDevice(psDevInfo->ui32DeviceID) !=
+                   PVRSRV_OK) {
+                       return PVRSRV_ERROR_GENERIC;
+               }
+
+               if (BCClosePVRServices(psDevInfo->hPVRServices) != PVRSRV_OK) {
+                       psDevInfo->hPVRServices = IMG_NULL;
+                       return PVRSRV_ERROR_GENERIC;
+               }
+
+               for (i = 0; i < psDevInfo->ui32NumBuffers; i++) {
+                       BCFreeContigMemory(psDevInfo->psSystemBuffer[i].
+                                          ui32Size,
+                                          psDevInfo->psSystemBuffer[i].
+                                          hMemHandle,
+                                          psDevInfo->psSystemBuffer[i].
+                                          sCPUVAddr,
+                                          SysPAddrToCpuPAddrBC(psDevInfo->
+                                                               psSystemBuffer
+                                                               [i].sSysAddr));
+               }
+
+               BCFreeKernelMem(psDevInfo);
+
+               SetAnchorPtr(IMG_NULL);
+       }
+
+       return PVRSRV_OK;
+}
diff --git a/pvr/bufferclass_example.h b/pvr/bufferclass_example.h
new file mode 100644 (file)
index 0000000..a31aa44
--- /dev/null
@@ -0,0 +1,132 @@
+/**********************************************************************
+ *
+ * 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 __BC_EXAMPLE_H__
+#define __BC_EXAMPLE_H__
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kernelbuffer.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+       extern IMG_IMPORT IMG_BOOL
+           PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE * psJTable);
+
+#define BC_EXAMPLE_NUM_BUFFERS 3
+
+#define YUV420 1
+#ifdef YUV420
+
+#define BC_EXAMPLE_WIDTH               (320)
+#define BC_EXAMPLE_HEIGHT              (160)
+#define BC_EXAMPLE_STRIDE              (320)
+#define BC_EXAMPLE_PIXELFORMAT (PVRSRV_PIXEL_FORMAT_NV12)
+
+#else
+#ifdef YUV422
+
+#define BC_EXAMPLE_WIDTH               (320)
+#define BC_EXAMPLE_HEIGHT              (160)
+#define BC_EXAMPLE_STRIDE              (320*2)
+#define BC_EXAMPLE_PIXELFORMAT (PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY)
+
+#else
+
+#define BC_EXAMPLE_WIDTH               (320)
+#define BC_EXAMPLE_HEIGHT              (160)
+#define BC_EXAMPLE_STRIDE              (320*2)
+#define BC_EXAMPLE_PIXELFORMAT (PVRSRV_PIXEL_FORMAT_RGB565)
+
+#endif
+#endif
+
+#define BC_EXAMPLE_DEVICEID             0
+
+       typedef struct BC_EXAMPLE_BUFFER_TAG {
+               IMG_UINT32 ui32Size;
+               IMG_HANDLE hMemHandle;
+               IMG_SYS_PHYADDR sSysAddr;
+               IMG_SYS_PHYADDR sPageAlignSysAddr;
+               IMG_CPU_VIRTADDR sCPUVAddr;
+               PVRSRV_SYNC_DATA *psSyncData;
+               struct BC_EXAMPLE_BUFFER_TAG *psNext;
+       } BC_EXAMPLE_BUFFER;
+
+       typedef struct BC_EXAMPLE_DEVINFO_TAG {
+               IMG_UINT32 ui32DeviceID;
+
+               BC_EXAMPLE_BUFFER *psSystemBuffer;
+
+               BUFFER_INFO sBufferInfo;
+
+               IMG_UINT32 ui32NumBuffers;
+
+               PVRSRV_BC_BUFFER2SRV_KMJTABLE sPVRJTable;
+
+               PVRSRV_BC_SRV2BUFFER_KMJTABLE sBCJTable;
+
+               IMG_HANDLE hPVRServices;
+
+               IMG_UINT32 ui32RefCount;
+
+       } BC_EXAMPLE_DEVINFO;
+
+       PVRSRV_ERROR BC_Example_Init(IMG_VOID);
+       PVRSRV_ERROR BC_Example_Deinit(IMG_VOID);
+
+       PVRSRV_ERROR BCOpenPVRServices(IMG_HANDLE * phPVRServices);
+       PVRSRV_ERROR BCClosePVRServices(IMG_HANDLE hPVRServices);
+
+       IMG_VOID *BCAllocKernelMem(IMG_UINT32 ui32Size);
+       IMG_VOID BCFreeKernelMem(IMG_VOID * pvMem);
+
+       PVRSRV_ERROR BCAllocContigMemory(IMG_UINT32 ui32Size,
+                                        IMG_HANDLE * phMemHandle,
+                                        IMG_CPU_VIRTADDR * pLinAddr,
+                                        IMG_CPU_PHYADDR * pPhysAddr);
+       IMG_VOID BCFreeContigMemory(IMG_UINT32 ui32Size,
+                                   IMG_HANDLE hMemHandle,
+                                   IMG_CPU_VIRTADDR LinAddr,
+                                   IMG_CPU_PHYADDR PhysAddr);
+
+       IMG_SYS_PHYADDR CpuPAddrToSysPAddrBC(IMG_CPU_PHYADDR cpu_paddr);
+       IMG_CPU_PHYADDR SysPAddrToCpuPAddrBC(IMG_SYS_PHYADDR sys_paddr);
+
+       IMG_VOID *MapPhysAddr(IMG_SYS_PHYADDR sSysAddr, IMG_UINT32 ui32Size);
+       IMG_VOID UnMapPhysAddr(IMG_VOID * pvAddr, IMG_UINT32 ui32Size);
+
+       PVRSRV_ERROR BCGetLibFuncAddr(IMG_HANDLE hExtDrv,
+                                     IMG_CHAR * szFunctionName,
+                                     PFN_BC_GET_PVRJTABLE * ppfnFuncTable);
+       BC_EXAMPLE_DEVINFO *GetAnchorPtr(IMG_VOID);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/bufferclass_example_linux.c b/pvr/bufferclass_example_linux.c
new file mode 100644 (file)
index 0000000..77ff988
--- /dev/null
@@ -0,0 +1,289 @@
+/**********************************************************************
+ *
+ * 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/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 "bufferclass_example.h"
+#include "bufferclass_example_linux.h"
+#include "pvrmodule.h"
+
+#define DEVNAME        "bc_example"
+#define        DRVNAME DEVNAME
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+int BC_Example_Bridge(struct inode *inode, struct file *file, unsigned int cmd,
+                     unsigned long arg);
+int FillBuffer(unsigned int ui32BufferIndex);
+int GetBufferCount(unsigned int *pui32BufferCount);
+
+static int AssignedMajorNumber;
+
+static struct file_operations bufferclass_example_fops = {
+ioctl: BC_Example_Bridge,
+};
+
+#define unref__ __attribute__ ((unused))
+
+#if defined(LMA)
+#define PVR_BUFFERCLASS_MEMOFFSET (220 * 1024 * 1024)
+#define PVR_BUFFERCLASS_MEMSIZE          (4 * 1024 * 1024)
+
+unsigned int g_ui32MemBase = 0;
+unsigned int g_ui32MemCurrent = 0;
+
+#define VENDOR_ID_PVR                                  0x1010
+#define DEVICE_ID_PVR                                  0x1CF1
+
+#define PVR_MEM_PCI_BASENUM                    2
+#endif
+
+static int __init BC_Example_ModInit(void)
+{
+#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_Example_ModInit:  pci_get_device failed\n");
+
+               goto ExitError;
+       }
+
+       if ((error = pci_enable_device(psPCIDev)) != 0) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Example_ModInit: pci_enable_device failed (%d)\n",
+                      error);
+               goto ExitError;
+       }
+#endif
+
+       AssignedMajorNumber =
+           register_chrdev(0, DEVNAME, &bufferclass_example_fops);
+
+       if (AssignedMajorNumber <= 0) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Example_ModInit: unable to get major number\n");
+
+               goto ExitDisable;
+       }
+#if defined(DEBUG)
+       printk(KERN_ERR DRVNAME ": BC_Example_ModInit: major device %d\n",
+              AssignedMajorNumber);
+#endif
+
+#if defined(LMA)
+
+       g_ui32MemBase =
+           pci_resource_start(psPCIDev,
+                              PVR_MEM_PCI_BASENUM) + PVR_BUFFERCLASS_MEMOFFSET;
+#endif
+
+       if (BC_Example_Init() != PVRSRV_OK) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Example_ModInit: can't init device\n");
+               goto ExitUnregister;
+       }
+#if defined(LMA)
+
+       pci_disable_device(psPCIDev);
+#endif
+
+       return 0;
+
+ExitUnregister:
+       unregister_chrdev(AssignedMajorNumber, DEVNAME);
+ExitDisable:
+#if defined(LMA)
+       pci_disable_device(psPCIDev);
+ExitError:
+#endif
+       return -EBUSY;
+}
+
+static void __exit BC_Example_ModCleanup(void)
+{
+       unregister_chrdev(AssignedMajorNumber, DEVNAME);
+
+       if (BC_Example_Deinit() != PVRSRV_OK) {
+               printk(KERN_ERR DRVNAME
+                      ": BC_Example_ModCleanup: can't deinit device\n");
+       }
+
+}
+
+IMG_VOID *BCAllocKernelMem(IMG_UINT32 ui32Size)
+{
+       return kmalloc(ui32Size, GFP_KERNEL);
+}
+
+IMG_VOID BCFreeKernelMem(IMG_VOID * pvMem)
+{
+       kfree(pvMem);
+}
+
+PVRSRV_ERROR BCAllocContigMemory(IMG_UINT32 ui32Size,
+                                IMG_HANDLE unref__ * phMemHandle,
+                                IMG_CPU_VIRTADDR * pLinAddr,
+                                IMG_CPU_PHYADDR * pPhysAddr)
+{
+#if defined(LMA)
+       IMG_VOID *pvLinAddr;
+
+       if (g_ui32MemCurrent + ui32Size >= PVR_BUFFERCLASS_MEMSIZE) {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       pvLinAddr = ioremap(g_ui32MemBase + g_ui32MemCurrent, ui32Size);
+
+       if (pvLinAddr) {
+               pPhysAddr->uiAddr = g_ui32MemBase + g_ui32MemCurrent;
+               *pLinAddr = pvLinAddr;
+
+               g_ui32MemCurrent += ui32Size;
+               return PVRSRV_OK;
+       }
+       return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+       dma_addr_t dma;
+       IMG_VOID *pvLinAddr;
+
+       pvLinAddr = dma_alloc_coherent(NULL, ui32Size, &dma, GFP_KERNEL);
+
+       if (pvLinAddr == IMG_NULL) {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       pPhysAddr->uiAddr = dma;
+       *pLinAddr = pvLinAddr;
+
+       return PVRSRV_OK;
+#endif
+}
+
+void BCFreeContigMemory(IMG_UINT32 ui32Size,
+                       IMG_HANDLE unref__ hMemHandle,
+                       IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr)
+{
+#if defined(LMA)
+       g_ui32MemCurrent -= ui32Size;
+       iounmap(LinAddr);
+#else
+       dma_free_coherent(NULL, ui32Size, LinAddr,
+                         (dma_addr_t) PhysAddr.uiAddr);
+#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;
+}
+
+PVRSRV_ERROR BCOpenPVRServices(IMG_HANDLE * phPVRServices)
+{
+
+       *phPVRServices = 0;
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BCClosePVRServices(IMG_HANDLE unref__ hPVRServices)
+{
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BCGetLibFuncAddr(IMG_HANDLE unref__ hExtDrv,
+                             IMG_CHAR * szFunctionName,
+                             PFN_BC_GET_PVRJTABLE * ppfnFuncTable)
+{
+       if (strcmp("PVRGetBufferClassJTable", szFunctionName) != 0)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       *ppfnFuncTable = PVRGetBufferClassJTable;
+
+       return PVRSRV_OK;
+}
+
+int BC_Example_Bridge(struct inode *inode, struct file *file, unsigned int cmd,
+                     unsigned long arg)
+{
+       int err = -EFAULT;
+       int command = _IOC_NR(cmd);
+       BC_Example_ioctl_package *psBridge = (BC_Example_ioctl_package *) arg;
+
+       if (!access_ok
+           (VERIFY_WRITE, psBridge, sizeof(BC_Example_ioctl_package)))
+               return err;
+
+       switch (command) {
+       case _IOC_NR(BC_Example_ioctl_fill_buffer):
+               {
+                       if (FillBuffer(psBridge->inputparam) == -1)
+                               return err;
+                       break;
+               }
+       case _IOC_NR(BC_Example_ioctl_get_buffer_count):
+               {
+                       if (GetBufferCount(&psBridge->outputparam) == -1)
+                               return err;
+
+                       break;
+               }
+       default:
+               return err;
+       }
+
+       return 0;
+}
+
+module_init(BC_Example_ModInit);
+module_exit(BC_Example_ModCleanup);
diff --git a/pvr/bufferclass_example_linux.h b/pvr/bufferclass_example_linux.h
new file mode 100644 (file)
index 0000000..bbaffee
--- /dev/null
@@ -0,0 +1,45 @@
+/**********************************************************************
+ *
+ * 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 __BC_EXAMPLE_LINUX_H__
+#define __BC_EXAMPLE_LINUX_H__
+
+#include <linux/ioctl.h>
+
+typedef struct BC_Example_ioctl_package_TAG {
+       int inputparam;
+       int outputparam;
+
+} BC_Example_ioctl_package;
+
+#define BC_EXAMPLE_IOC_GID      'g'
+
+#define BC_EXAMPLE_IOWR(INDEX)  _IOWR(BC_EXAMPLE_IOC_GID, INDEX, BC_Example_ioctl_package)
+
+#define BC_Example_ioctl_fill_buffer           BC_EXAMPLE_IOWR(0)
+#define BC_Example_ioctl_get_buffer_count      BC_EXAMPLE_IOWR(1)
+
+#endif
diff --git a/pvr/bufferclass_example_private.c b/pvr/bufferclass_example_private.c
new file mode 100644 (file)
index 0000000..fb3f1d0
--- /dev/null
@@ -0,0 +1,226 @@
+/**********************************************************************
+ *
+ * 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 "bufferclass_example.h"
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+void FillYUV420Image(void *pvDest, int width, int height, int bytestride)
+{
+       static int iPhase = 0;
+       int i, j;
+       unsigned char u, v, y;
+       unsigned char *pui8y = (unsigned char *)pvDest;
+       unsigned short *pui16uv;
+       unsigned int count = 0;
+
+       for (j = 0; j < height; j++) {
+               for (i = 0; i < width; i++) {
+                       y = (((i + iPhase) >> 6) % (2) == 0) ? 0x7f : 0x00;
+
+                       pui8y[count++] = y;
+               }
+       }
+
+       pui16uv =
+           (unsigned short *)((unsigned char *)pvDest + (width * height));
+       count = 0;
+
+       for (j = 0; j < height; j += 2) {
+               for (i = 0; i < width; i += 2) {
+                       u = (j <
+                            (height / 2)) ? ((i <
+                                              (width /
+                                               2)) ? 0xFF : 0x33) : ((i <
+                                                                      (width /
+                                                                       2)) ?
+                                                                     0x33 :
+                                                                     0xAA);
+                       v = (j <
+                            (height / 2)) ? ((i <
+                                              (width /
+                                               2)) ? 0xAC : 0x0) : ((i <
+                                                                     (width /
+                                                                      2)) ?
+                                                                    0x03 :
+                                                                    0xEE);
+
+                       pui16uv[count++] = (v << 8) | u;
+
+               }
+       }
+
+       iPhase++;
+}
+
+void FillYUV422Image(void *pvDest, int width, int height, int bytestride)
+{
+       static int iPhase = 0;
+       int x, y;
+       unsigned char u, v, y0, y1;
+       unsigned int *pui32yuv = (unsigned int *)pvDest;
+       unsigned int count = 0;
+
+       for (y = 0; y < height; y++) {
+               for (x = 0; x < width; x += 2) {
+                       u = (y <
+                            (height / 2)) ? ((x <
+                                              (width /
+                                               2)) ? 0xFF : 0x33) : ((x <
+                                                                      (width /
+                                                                       2)) ?
+                                                                     0x33 :
+                                                                     0xAA);
+                       v = (y <
+                            (height / 2)) ? ((x <
+                                              (width /
+                                               2)) ? 0xAA : 0x0) : ((x <
+                                                                     (width /
+                                                                      2)) ?
+                                                                    0x03 :
+                                                                    0xEE);
+
+                       y0 = y1 =
+                           (((x + iPhase) >> 6) % (2) == 0) ? 0x7f : 0x00;
+
+                       pui32yuv[count++] =
+                           (y1 << 24) | (v << 16) | (y0 << 8) | u;
+
+               }
+       }
+
+       iPhase++;
+}
+
+void FillRGB565Image(void *pvDest, int width, int height, int bytestride)
+{
+       int i, Count;
+       unsigned long *pui32Addr = (unsigned long *)pvDest;
+       unsigned short *pui16Addr = (unsigned short *)pvDest;
+       unsigned long Colour32;
+       unsigned short Colour16;
+       static unsigned char Colour8 = 0;
+
+       Colour16 =
+           (Colour8 >> 3) | ((Colour8 >> 2) << 5) | ((Colour8 >> 3) << 11);
+       Colour32 = Colour16 | Colour16 << 16;
+
+       Count = (height * bytestride) >> 2;
+
+       for (i = 0; i < Count; i++) {
+               pui32Addr[i] = Colour32;
+       }
+
+       Count = height;
+
+       pui16Addr = (unsigned short *)((unsigned char *)pvDest + (2 * Colour8));
+
+       for (i = 0; i < Count; i++) {
+               *pui16Addr = 0xF800;
+
+               pui16Addr =
+                   (unsigned short *)((unsigned char *)pui16Addr + bytestride);
+       }
+       Count = bytestride >> 2;
+
+       pui32Addr =
+           (unsigned long *)((unsigned char *)pvDest +
+                             (bytestride * (MIN(height - 1, 0xFF) - Colour8)));
+
+       for (i = 0; i < Count; i++) {
+               pui32Addr[i] = 0x001F001F;
+       }
+
+       Colour8 = (Colour8 + 1) % MIN(height - 1, 0xFF);
+}
+
+int FillBuffer(unsigned int ui32BufferIndex)
+{
+       BC_EXAMPLE_DEVINFO *psDevInfo = GetAnchorPtr();
+       BC_EXAMPLE_BUFFER *psBuffer;
+       BUFFER_INFO *psBufferInfo;
+       PVRSRV_SYNC_DATA *psSyncData;
+
+       if (psDevInfo == IMG_NULL) {
+               return -1;
+       }
+
+       psBuffer = &psDevInfo->psSystemBuffer[ui32BufferIndex];
+       psBufferInfo = &psDevInfo->sBufferInfo;
+
+       psSyncData = psBuffer->psSyncData;
+
+       if (psSyncData) {
+
+               if (psSyncData->ui32ReadOpsPending !=
+                   psSyncData->ui32ReadOpsComplete) {
+                       return -1;
+               }
+
+               psSyncData->ui32WriteOpsPending++;
+       }
+
+       switch (psBufferInfo->pixelformat) {
+       case PVRSRV_PIXEL_FORMAT_RGB565:
+       default:
+               {
+                       FillRGB565Image(psBuffer->sCPUVAddr, BC_EXAMPLE_WIDTH,
+                                       BC_EXAMPLE_HEIGHT, BC_EXAMPLE_STRIDE);
+                       break;
+               }
+       case PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY:
+               {
+                       FillYUV422Image(psBuffer->sCPUVAddr, BC_EXAMPLE_WIDTH,
+                                       BC_EXAMPLE_HEIGHT, BC_EXAMPLE_STRIDE);
+                       break;
+               }
+       case PVRSRV_PIXEL_FORMAT_NV12:
+               {
+                       FillYUV420Image(psBuffer->sCPUVAddr, BC_EXAMPLE_WIDTH,
+                                       BC_EXAMPLE_HEIGHT, BC_EXAMPLE_STRIDE);
+                       break;
+               }
+       }
+
+       if (psSyncData) {
+               psSyncData->ui32WriteOpsComplete++;
+       }
+
+       return 0;
+}
+
+int GetBufferCount(unsigned int *pui32BufferCount)
+{
+       BC_EXAMPLE_DEVINFO *psDevInfo = GetAnchorPtr();
+
+       if (psDevInfo == IMG_NULL) {
+               return -1;
+       }
+
+       *pui32BufferCount = psDevInfo->sBufferInfo.ui32BufferCount;
+
+       return 0;
+}
diff --git a/pvr/dbgdrvif.h b/pvr/dbgdrvif.h
new file mode 100644 (file)
index 0000000..cf04501
--- /dev/null
@@ -0,0 +1,283 @@
+/**********************************************************************
+ *
+ * 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                   0x00000001
+#define DEBUG_CAPMODE_CONTINUOUS               0x00000002
+#define DEBUG_CAPMODE_HOTKEY                   0x00000004
+
+#define DEBUG_OUTMODE_STANDARDDBG              0x00000001
+#define DEBUG_OUTMODE_MONO                             0x00000002
+#define DEBUG_OUTMODE_STREAMENABLE             0x00000004
+#define DEBUG_OUTMODE_ASYNC                            0x00000008
+#define DEBUG_OUTMODE_SGXVGA            0x00000010
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM   0x00000001
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION  0x00000002
+#define DEBUG_FLAGS_ENABLESAMPLE               0x00000004
+
+#define DEBUG_FLAGS_TEXTSTREAM                 0x80000000
+
+#define DEBUG_LEVEL_0                                  0x00000001
+#define DEBUG_LEVEL_1                                  0x00000003
+#define DEBUG_LEVEL_2                                  0x00000007
+#define DEBUG_LEVEL_3                                  0x0000000F
+#define DEBUG_LEVEL_4                                  0x0000001F
+#define DEBUG_LEVEL_5                                  0x0000003F
+#define DEBUG_LEVEL_6                                  0x0000007F
+#define DEBUG_LEVEL_7                                  0x000000FF
+#define DEBUG_LEVEL_8                                  0x000001FF
+#define DEBUG_LEVEL_9                                  0x000003FF
+#define DEBUG_LEVEL_10                                 0x000007FF
+#define DEBUG_LEVEL_11                                 0x00000FFF
+
+#define DEBUG_LEVEL_SEL0                               0x00000001
+#define DEBUG_LEVEL_SEL1                               0x00000002
+#define DEBUG_LEVEL_SEL2                               0x00000004
+#define DEBUG_LEVEL_SEL3                               0x00000008
+#define DEBUG_LEVEL_SEL4                               0x00000010
+#define DEBUG_LEVEL_SEL5                               0x00000020
+#define DEBUG_LEVEL_SEL6                               0x00000040
+#define DEBUG_LEVEL_SEL7                               0x00000080
+#define DEBUG_LEVEL_SEL8                               0x00000100
+#define DEBUG_LEVEL_SEL9                               0x00000200
+#define DEBUG_LEVEL_SEL10                              0x00000400
+#define DEBUG_LEVEL_SEL11                              0x00000800
+
+#define DEBUG_SERVICE_IOCTL_BASE               0x800
+#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)
+
+typedef struct _DBG_IN_CREATESTREAM_ {
+       IMG_UINT32 ui32Pages;
+       IMG_UINT32 ui32CapMode;
+       IMG_UINT32 ui32OutMode;
+       IMG_CHAR *pszName;
+} DBG_IN_CREATESTREAM, *PDBG_IN_CREATESTREAM;
+
+typedef struct _DBG_IN_FINDSTREAM_ {
+       IMG_BOOL bResetStream;
+       IMG_CHAR *pszName;
+} DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
+
+typedef struct _DBG_IN_WRITESTRING_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Level;
+       IMG_CHAR *pszString;
+} DBG_IN_WRITESTRING, *PDBG_IN_WRITESTRING;
+
+typedef struct _DBG_IN_READSTRING_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32StringLen;
+       IMG_CHAR *pszString;
+} DBG_IN_READSTRING, *PDBG_IN_READSTRING;
+
+typedef struct _DBG_IN_SETDEBUGMODE_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Mode;
+       IMG_UINT32 ui32Start;
+       IMG_UINT32 ui32End;
+       IMG_UINT32 ui32SampleRate;
+} DBG_IN_SETDEBUGMODE, *PDBG_IN_SETDEBUGMODE;
+
+typedef struct _DBG_IN_SETDEBUGOUTMODE_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Mode;
+} DBG_IN_SETDEBUGOUTMODE, *PDBG_IN_SETDEBUGOUTMODE;
+
+typedef struct _DBG_IN_SETDEBUGLEVEL_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Level;
+} DBG_IN_SETDEBUGLEVEL, *PDBG_IN_SETDEBUGLEVEL;
+
+typedef struct _DBG_IN_SETFRAME_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Frame;
+} DBG_IN_SETFRAME, *PDBG_IN_SETFRAME;
+
+typedef struct _DBG_IN_WRITE_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Level;
+       IMG_UINT32 ui32TransferSize;
+       IMG_UINT8 *pui8InBuffer;
+} DBG_IN_WRITE, *PDBG_IN_WRITE;
+
+typedef struct _DBG_IN_READ_ {
+       IMG_VOID *pvStream;
+       IMG_BOOL bReadInitBuffer;
+       IMG_UINT32 ui32OutBufferSize;
+       IMG_UINT8 *pui8OutBuffer;
+} DBG_IN_READ, *PDBG_IN_READ;
+
+typedef struct _DBG_IN_OVERRIDEMODE_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Mode;
+} DBG_IN_OVERRIDEMODE, *PDBG_IN_OVERRIDEMODE;
+
+typedef struct _DBG_IN_ISCAPTUREFRAME_ {
+       IMG_VOID *pvStream;
+       IMG_BOOL bCheckPreviousFrame;
+} DBG_IN_ISCAPTUREFRAME, *PDBG_IN_ISCAPTUREFRAME;
+
+typedef struct _DBG_IN_SETMARKER_ {
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Marker;
+} DBG_IN_SETMARKER, *PDBG_IN_SETMARKER;
+
+typedef struct _DBG_IN_WRITE_LF_ {
+       IMG_UINT32 ui32Flags;
+       IMG_VOID *pvStream;
+       IMG_UINT32 ui32Level;
+       IMG_UINT32 ui32BufferSize;
+       IMG_UINT8 *pui8InBuffer;
+} DBG_IN_WRITE_LF, *PDBG_IN_WRITE_LF;
+
+#define WRITELF_FLAGS_RESETBUF         0x00000001
+
+typedef struct _DBG_STREAM_ {
+       struct _DBG_STREAM_ *psNext;
+       struct _DBG_STREAM_ *psInitStream;
+       IMG_BOOL bInitPhaseComplete;
+       IMG_UINT32 ui32Flags;
+       IMG_UINT32 ui32Base;
+       IMG_UINT32 ui32Size;
+       IMG_UINT32 ui32RPtr;
+       IMG_UINT32 ui32WPtr;
+       IMG_UINT32 ui32DataWritten;
+       IMG_UINT32 ui32CapMode;
+       IMG_UINT32 ui32OutMode;
+       IMG_UINT32 ui32DebugLevel;
+       IMG_UINT32 ui32DefaultMode;
+       IMG_UINT32 ui32Start;
+       IMG_UINT32 ui32End;
+       IMG_UINT32 ui32Current;
+       IMG_UINT32 ui32Access;
+       IMG_UINT32 ui32SampleRate;
+       IMG_UINT32 ui32Reserved;
+       IMG_UINT32 ui32Timeout;
+       IMG_UINT32 ui32Marker;
+       IMG_CHAR szName[30];
+} DBG_STREAM, *PDBG_STREAM;
+
+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 * pfnEndInitPhase) (PDBG_STREAM psStream);
+        IMG_UINT32(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_UINT32(IMG_CALLCONV *
+                   pfnIsLastCaptureFrame) (PDBG_STREAM psStream);
+} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+
+#endif
diff --git a/pvr/device.h b/pvr/device.h
new file mode 100644 (file)
index 0000000..2eb003d
--- /dev/null
@@ -0,0 +1,251 @@
+/**********************************************************************
+ *
+ * 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 "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;
+
+       } 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;
+
+               DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeapInfo;
+
+       } DEV_ARENA_DESCRIPTOR;
+
+       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(*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 **);
+                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);
+
+                IMG_DEV_PHYADDR(*pfnMMUGetPhysPageAddr) (MMU_HEAP * pMMUHeap,
+                                                         IMG_DEV_VIRTADDR
+                                                         sDevVPageAddr);
+                IMG_DEV_PHYADDR(*pfnMMUGetPDDevPAddr) (MMU_CONTEXT *
+                                                       pMMUContext);
+
+                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;
+               IMG_VOID *hDeviceOSMemHandle;
+
+               PRESMAN_CONTEXT hResManContext;
+
+               PSYS_DATA psSysData;
+
+               RA_ARENA *psLocalDevMemArena;
+
+               IMG_UINT32 ui32Flags;
+
+               struct _PVRSRV_DEVICE_NODE_ *psNext;
+       } 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 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
+                                                           ui32Waitus,
+                                                           IMG_UINT32
+                                                           ui32Tries);
+
+#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/pvr/deviceclass.c b/pvr/deviceclass.c
new file mode 100644 (file)
index 0000000..1385115
--- /dev/null
@@ -0,0 +1,1584 @@
+/**********************************************************************
+ *
+ * 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 "pvr_bridge_km.h"
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA * psSysData, IMG_UINT32 * pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA * psSysData, IMG_UINT32 ui32DevID);
+
+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;
+       PVRSRV_QUEUE_INFO *psQueue;
+       PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+       IMG_UINT32 ui32BufferCount;
+       PVRSRV_DC_BUFFER *psLastFlipBuffer;
+       struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+       IMG_HANDLE hResItem;
+} PVRSRV_DC_SWAPCHAIN;
+
+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;
+} 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;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS DeviceClass,
+                                    IMG_UINT32 * pui32DevCount,
+                                    IMG_UINT32 * pui32DevID)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_UINT ui32DevCount = 0;
+       SYS_DATA *psSysData;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVEnumerateDCKM: Failed to get SysData"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       while (psDeviceNode) {
+               if ((psDeviceNode->sDevId.eDeviceClass == DeviceClass)
+                   && (psDeviceNode->sDevId.eDeviceType ==
+                       PVRSRV_DEVICE_TYPE_EXT)) {
+                       ui32DevCount++;
+                       if (pui32DevID) {
+                               *pui32DevID++ =
+                                   psDeviceNode->sDevId.ui32DeviceIndex;
+                       }
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       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;
+}
+
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM(PVRSRV_DC_SRV2DISP_KMJTABLE * psFuncTable,
+                                     IMG_UINT32 * pui32DeviceID)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       SYS_DATA *psSysData;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRegisterDCDeviceKM: Failed to get SysData"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(*psDCInfo),
+                      (IMG_VOID **) & psDCInfo, IMG_NULL) != 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) != 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) != 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;
+
+       AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+       psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+       if (pui32DeviceID) {
+               *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+       }
+
+       SysRegisterExternalDevice(psDeviceNode);
+
+       psDeviceNode->psNext = psSysData->psDeviceNodeList;
+       psSysData->psDeviceNodeList = psDeviceNode;
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       if (psDCInfo->psFuncTable) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo->psFuncTable,
+                         IMG_NULL);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo, IMG_NULL);
+
+       return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+       SYS_DATA *psSysData;
+       PVRSRV_DEVICE_NODE **ppsDeviceNode, *psDeviceNode;
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRemoveDCDeviceKM: Failed to get SysData"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       ppsDeviceNode = &psSysData->psDeviceNodeList;
+       while (*ppsDeviceNode) {
+               switch ((*ppsDeviceNode)->sDevId.eDeviceClass) {
+               case PVRSRV_DEVICE_CLASS_DISPLAY:
+                       {
+                               if ((*ppsDeviceNode)->sDevId.ui32DeviceIndex ==
+                                   ui32DevIndex) {
+                                       goto FoundDevice;
+                               }
+                               break;
+                       }
+               default:
+                       {
+                               break;
+                       }
+               }
+               ppsDeviceNode = &((*ppsDeviceNode)->psNext);
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVRemoveDCDeviceKM: requested device %d not present",
+                ui32DevIndex));
+
+       return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+       psDeviceNode = *ppsDeviceNode;
+       *ppsDeviceNode = psDeviceNode->psNext;
+
+       SysRemoveExternalDevice(psDeviceNode);
+
+       psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice;
+       PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+       FreeDeviceID(psSysData, ui32DevIndex);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo->psFuncTable, IMG_NULL);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo, IMG_NULL);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDeviceNode, IMG_NULL);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVRegisterBCDeviceKM(PVRSRV_BC_SRV2BUFFER_KMJTABLE *
+                                     psFuncTable, IMG_UINT32 * pui32DeviceID)
+{
+       PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       SYS_DATA *psSysData;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRegisterBCDeviceKM: Failed to get SysData"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(*psBCInfo),
+                      (IMG_VOID **) & psBCInfo, IMG_NULL) != 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) != 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) != 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;
+
+       AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+       psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+       if (pui32DeviceID) {
+               *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+       }
+
+       psDeviceNode->psNext = psSysData->psDeviceNodeList;
+       psSysData->psDeviceNodeList = psDeviceNode;
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       if (psBCInfo->psFuncTable) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo->psFuncTable,
+                         IMG_NULL);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo, IMG_NULL);
+
+       return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+       SYS_DATA *psSysData;
+       PVRSRV_DEVICE_NODE **ppsDevNode, *psDevNode;
+       PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRemoveBCDeviceKM: Failed to get SysData"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       ppsDevNode = &psSysData->psDeviceNodeList;
+       while (*ppsDevNode) {
+               switch ((*ppsDevNode)->sDevId.eDeviceClass) {
+               case PVRSRV_DEVICE_CLASS_BUFFER:
+                       {
+                               if ((*ppsDevNode)->sDevId.ui32DeviceIndex ==
+                                   ui32DevIndex) {
+                                       goto FoundDevice;
+                               }
+                               break;
+                       }
+               default:
+                       {
+                               break;
+                       }
+               }
+               ppsDevNode = &(*ppsDevNode)->psNext;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVRemoveBCDeviceKM: requested device %d not present",
+                ui32DevIndex));
+
+       return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+       psDevNode = *(ppsDevNode);
+       *ppsDevNode = psDevNode->psNext;
+
+       FreeDeviceID(psSysData, ui32DevIndex);
+       psBCInfo = (PVRSRV_BUFFERCLASS_INFO *) psDevNode->pvDevice;
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo->psFuncTable, IMG_NULL);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo, IMG_NULL);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDevNode, IMG_NULL);
+       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);
+
+               PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.
+                                    psKernelSyncInfo);
+
+               psDCInfo->hDevMemContext = IMG_NULL;
+               psDCInfo->hExtDevice = IMG_NULL;
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, 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;
+
+       if (!phDeviceKM) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVOpenDCDeviceKM: Invalid params"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVOpenDCDeviceKM: Failed to get SysData"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       while (psDeviceNode) {
+               if ((psDeviceNode->sDevId.eDeviceClass ==
+                    PVRSRV_DEVICE_CLASS_DISPLAY)
+                   && (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) {
+
+                       psDCInfo =
+                           (PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice;
+                       goto FoundDevice;
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVOpenDCDeviceKM: no devnode matching index %d",
+                ui32DeviceID));
+
+       return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(*psDCPerContextInfo),
+                      (IMG_VOID **) & psDCPerContextInfo,
+                      IMG_NULL) != 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) {
+               PVRSRV_ERROR eError;
+
+               psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+               PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+               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;
+               }
+       }
+
+       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 hSwapChain)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if (!hSwapChain) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psSwapChain = hSwapChain;
+
+       eError = ResManFreeResByPtr(psSwapChain->hResItem);
+
+       return eError;
+}
+
+static PVRSRV_ERROR DestroyDCSwapChainCallBack(IMG_PVOID pvParam,
+                                              IMG_UINT32 ui32Param)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain = pvParam;
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
+       IMG_UINT32 i;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       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) {
+                       PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].
+                                            sDeviceClassBuffer.
+                                            psKernelSyncInfo);
+               }
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSwapChain, IMG_NULL);
+
+       return eError;
+}
+
+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 * phSwapChain,
+                                          IMG_UINT32 * pui32SwapChainID)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL;
+       PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+       PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 i;
+
+       if (!hDeviceKM
+           || !psDstSurfAttrib
+           || !psSrcSurfAttrib || !phSwapChain || !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 (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(PVRSRV_DC_SWAPCHAIN),
+                      (IMG_VOID **) & psSwapChain, IMG_NULL) != 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.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;
+
+       eError =
+           psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+                                                       ui32Flags,
+                                                       psDstSurfAttrib,
+                                                       psSrcSurfAttrib,
+                                                       ui32BufferCount,
+                                                       apsSyncData,
+                                                       ui32OEMFlags,
+                                                       &psSwapChain->
+                                                       hExtSwapChain,
+                                                       pui32SwapChainID);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
+               goto ErrorExit;
+       }
+
+       *phSwapChain = (IMG_HANDLE) psSwapChain;
+
+       psSwapChain->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+                                                 RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN,
+                                                 psSwapChain,
+                                                 0,
+                                                 DestroyDCSwapChainCallBack);
+
+       return eError;
+
+ErrorExit:
+
+       for (i = 0; i < ui32BufferCount; i++) {
+               if (psSwapChain->asBuffer[i].sDeviceClassBuffer.
+                   psKernelSyncInfo) {
+                       PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].
+                                            sDeviceClassBuffer.
+                                            psKernelSyncInfo);
+               }
+       }
+
+       if (psQueue) {
+               PVRSRVDestroyCommandQueueKM(psQueue);
+       }
+
+       if (psSwapChain) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSwapChain, IMG_NULL);
+       }
+
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM,
+                                     IMG_HANDLE hSwapChain, IMG_RECT * psRect)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if (!hDeviceKM || !hSwapChain) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVSetDCDstRectKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = (PVRSRV_DC_SWAPCHAIN *) hSwapChain;
+
+       return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+                                                     psSwapChain->
+                                                     hExtSwapChain, psRect);
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM,
+                                     IMG_HANDLE hSwapChain, IMG_RECT * psRect)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if (!hDeviceKM || !hSwapChain) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVSetDCSrcRectKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = (PVRSRV_DC_SWAPCHAIN *) hSwapChain;
+
+       return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+                                                     psSwapChain->
+                                                     hExtSwapChain, psRect);
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM,
+                                          IMG_HANDLE hSwapChain,
+                                          IMG_UINT32 ui32CKColour)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if (!hDeviceKM || !hSwapChain) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = (PVRSRV_DC_SWAPCHAIN *) hSwapChain;
+
+       return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+                                                          psSwapChain->
+                                                          hExtSwapChain,
+                                                          ui32CKColour);
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM,
+                                          IMG_HANDLE hSwapChain,
+                                          IMG_UINT32 ui32CKColour)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+       if (!hDeviceKM || !hSwapChain) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = (PVRSRV_DC_SWAPCHAIN *) hSwapChain;
+
+       return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+                                                          psSwapChain->
+                                                          hExtSwapChain,
+                                                          ui32CKColour);
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
+                                     IMG_HANDLE hSwapChain,
+                                     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 || !hSwapChain || !phBuffer) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVGetDCBuffersKM: Invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psSwapChain = (PVRSRV_DC_SWAPCHAIN *) hSwapChain;
+
+       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_ERROR eError;
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_BUFFER *psBuffer;
+       PVRSRV_QUEUE_INFO *psQueue;
+       DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+       IMG_UINT32 i;
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0;
+       IMG_UINT32 ui32NumSrcSyncs = 1;
+       PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+       PVRSRV_COMMAND *psCommand;
+
+       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
+
+       psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+       psBuffer = (PVRSRV_DC_BUFFER *) hBuffer;
+
+       psQueue = psBuffer->psSwapChain->psQueue;
+
+       apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+       if (psBuffer->psSwapChain->psLastFlipBuffer &&
+           psBuffer != psBuffer->psSwapChain->psLastFlipBuffer) {
+               apsSrcSync[1] =
+                   psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.
+                   psKernelSyncInfo;
+               ui32NumSrcSyncs++;
+       }
+
+       eError = PVRSRVInsertCommandKM(psQueue,
+                                      &psCommand,
+                                      psDCInfo->ui32DeviceID,
+                                      DC_FLIP_COMMAND,
+                                      0,
+                                      IMG_NULL,
+                                      ui32NumSrcSyncs,
+                                      apsSrcSync,
+                                      sizeof(DISPLAYCLASS_FLIP_COMMAND) +
+                                      (sizeof(IMG_RECT) * ui32ClipRectCount));
+       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;
+       }
+
+       do {
+               if (PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) !=
+                   PVRSRV_ERROR_PROCESSING_BLOCKED) {
+                       goto ProcessedQueues;
+               }
+
+               if (bStart == IMG_FALSE) {
+                       uiStart = OSClockus();
+                       bStart = IMG_TRUE;
+               }
+               OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+       } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVSwapToDCBufferKM: Failed to process queues"));
+
+       eError = PVRSRV_ERROR_GENERIC;
+       goto Exit;
+
+ProcessedQueues:
+
+       psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
+
+Exit:
+#if defined(SUPPORT_LMA)
+       PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+                                       IMG_HANDLE hSwapChain)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_QUEUE_INFO *psQueue;
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DC_SWAPCHAIN *psSwapChain;
+       DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0;
+       IMG_UINT32 ui32NumSrcSyncs = 1;
+       PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+       PVRSRV_COMMAND *psCommand;
+
+       if (!hDeviceKM || !hSwapChain) {
+               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);
+       psSwapChain = (PVRSRV_DC_SWAPCHAIN *) hSwapChain;
+
+       psQueue = psSwapChain->psQueue;
+
+       apsSrcSync[0] =
+           psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
+       if (psSwapChain->psLastFlipBuffer) {
+               apsSrcSync[1] =
+                   psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.
+                   psKernelSyncInfo;
+               ui32NumSrcSyncs++;
+       }
+
+       eError = PVRSRVInsertCommandKM(psQueue,
+                                      &psCommand,
+                                      psDCInfo->ui32DeviceID,
+                                      DC_FLIP_COMMAND,
+                                      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;
+       }
+
+       do {
+               if (PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) !=
+                   PVRSRV_ERROR_PROCESSING_BLOCKED) {
+                       goto ProcessedQueues;
+               }
+
+               if (bStart == IMG_FALSE) {
+                       uiStart = OSClockus();
+                       bStart = IMG_TRUE;
+               }
+               OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+       } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVSwapToDCSystemKM: Failed to process queues"));
+       eError = PVRSRV_ERROR_GENERIC;
+       goto Exit;
+
+ProcessedQueues:
+
+       psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
+
+       eError = PVRSRV_OK;
+
+Exit:
+#if defined(SUPPORT_LMA)
+       PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+       return eError;
+}
+
+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);
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRegisterSystemISRHandler: Failed to get SysData"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       psDevNode = psSysData->psDeviceNodeList;
+       while (psDevNode) {
+               if (psDevNode->sDevId.ui32DeviceIndex == ui32DeviceID) {
+                       break;
+               }
+               psDevNode = psDevNode->psNext;
+       }
+
+       psDevNode->pvISRData = (IMG_VOID *) pvISRHandlerData;
+
+       psDevNode->pfnDeviceISR = pfnISRHandler;
+
+       return PVRSRV_OK;
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
+{
+       PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       SYS_DATA *psSysData;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVSetDCState: Failed to get SysData"));
+               return;
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       while (psDeviceNode != IMG_NULL) {
+               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);
+                       }
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+}
+
+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;
+       psJTable->pfnPVRSRVCmdComplete = PVRSRVCommandCompleteKM;
+       psJTable->pfnPVRSRVRegisterSystemISRHandler =
+           PVRSRVRegisterSystemISRHandler;
+       psJTable->pfnPVRSRVRegisterPowerDevice = PVRSRVRegisterPowerDevice;
+
+       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->hExtDevice);
+
+               for (i = 0; i < psBCInfo->ui32BufferCount; i++) {
+                       if (psBCInfo->psBuffer[i].sDeviceClassBuffer.
+                           psKernelSyncInfo) {
+                               PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].
+                                                    sDeviceClassBuffer.
+                                                    psKernelSyncInfo);
+                       }
+               }
+
+               if (psBCInfo->psBuffer) {
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0,
+                                 psBCInfo->psBuffer, IMG_NULL);
+               }
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, 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) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVOpenBCDeviceKM: Invalid params"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVOpenBCDeviceKM: Failed to get SysData"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       while (psDeviceNode) {
+               if ((psDeviceNode->sDevId.eDeviceClass ==
+                    PVRSRV_DEVICE_CLASS_BUFFER)
+                   && (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) {
+
+                       psBCInfo =
+                           (PVRSRV_BUFFERCLASS_INFO *) psDeviceNode->pvDevice;
+                       goto FoundDevice;
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVOpenBCDeviceKM: No devnode matching index %d",
+                ui32DeviceID));
+
+       return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(*psBCPerContextInfo),
+                      (IMG_VOID **) & psBCPerContextInfo,
+                      IMG_NULL) != 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;
+               PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+               psBCInfo->hDevMemContext =
+                   (IMG_HANDLE) psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+               eError =
+                   psBCInfo->psFuncTable->pfnOpenBCDevice(&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);
+               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;
+                       }
+
+                       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) {
+                       PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].
+                                            sDeviceClassBuffer.
+                                            psKernelSyncInfo);
+               }
+       }
+
+       if (psBCInfo->psBuffer) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, 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->pfnPVRSRVRemoveBCDevice = PVRSRVRemoveBCDeviceKM;
+
+       return IMG_TRUE;
+}
diff --git a/pvr/devicemem.c b/pvr/devicemem.c
new file mode 100644 (file)
index 0000000..88cc6f3
--- /dev/null
@@ -0,0 +1,1049 @@
+/**********************************************************************
+ *
+ * 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 "sgxmmu.h"
+#include "sgxapi_km.h"
+#include "pvr_bridge_km.h"
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
+                                  IMG_HANDLE hDevMemHeap,
+                                  IMG_UINT32 ui32Flags,
+                                  IMG_UINT32 ui32Size,
+                                  IMG_UINT32 ui32Alignment,
+                                  PVRSRV_KERNEL_MEM_INFO ** ppsMemInfo);
+
+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;
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+       PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+       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) SGX_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
+#if defined(PVR_SECURE_HANDLES)
+                                                            ,
+                                                            IMG_BOOL * pbShared
+#endif
+    )
+{
+       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;
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+       PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+       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
+#if defined(PVR_SECURE_HANDLES)
+                                                          , IMG_BOOL * pbShared
+#endif
+    )
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_UINT32 ui32HeapCount, ui32ClientHeapCount = 0;
+       DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+       IMG_HANDLE hDevMemHeap;
+       IMG_UINT32 i;
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+       PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+       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_UINT32 ui32Size,
+                                  IMG_UINT32 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_OS_PAGEABLE_HEAP,
+                      sizeof(PVRSRV_KERNEL_MEM_INFO),
+                      (IMG_VOID **) & psMemInfo, IMG_NULL) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "AllocDeviceMem: Failed to alloc memory for block"));
+               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+       }
+
+       psMemBlock = &(psMemInfo->sMemBlk);
+
+       psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+       bBMError = BM_Alloc(hDevMemHeap,
+                           IMG_NULL,
+                           ui32Size,
+                           &psMemInfo->ui32Flags, ui32Alignment, &hBuffer);
+
+       if (!bBMError) {
+               PVR_DPF((PVR_DBG_ERROR, "AllocDeviceMem: BM_Alloc Failed"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, 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 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, 0,
+                         psMemInfo->pvSysBackupBuffer, IMG_NULL);
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, 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_OS_PAGEABLE_HEAP,
+                           sizeof(PVRSRV_KERNEL_SYNC_INFO),
+                           (IMG_VOID **) & psKernelSyncInfo, IMG_NULL);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       pBMContext = (BM_CONTEXT *) hDevMemContext;
+       psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+       hSyncDevMemHeap =
+           psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
+                                               ui32SyncHeapID].hDevMemHeap;
+
+       eError = AllocDeviceMem(hDevCookie,
+                               hSyncDevMemHeap,
+                               0,
+                               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_OS_PAGEABLE_HEAP, 0, 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;
+
+       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)
+{
+       FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psKernelSyncInfo, IMG_NULL);
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID pvParam,
+                                         IMG_UINT32 ui32Param)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       if (psMemInfo->psKernelSyncInfo) {
+               eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+       }
+
+       if (eError == PVRSRV_OK) {
+               eError = FreeDeviceMem(psMemInfo);
+       }
+
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
+                                                   PVRSRV_KERNEL_MEM_INFO *
+                                                   psMemInfo)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+       if (!psMemInfo) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (psMemInfo->sMemBlk.hResItem != IMG_NULL) {
+               eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+       } else {
+
+               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_UINT32 ui32Size,
+                                                    IMG_UINT32 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;
+       }
+
+       eError = AllocDeviceMem(hDevCookie,
+                               hDevMemHeap,
+                               ui32Flags, ui32Size, ui32Alignment, &psMemInfo);
+
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       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;
+               }
+       }
+
+       *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;
+               }
+       }
+
+       return (PVRSRV_OK);
+
+free_mainalloc:
+       FreeDeviceMem(psMemInfo);
+
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
+                                                         PVRSRV_KERNEL_MEM_INFO
+                                                         * psMemInfo)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevCookie;
+
+       PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+       if (!psMemInfo) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       ResManDissociateRes(psMemInfo->sMemBlk.hResItem,
+                           psDeviceNode->hResManContext);
+
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+                                                      IMG_UINT32 * pui32Total,
+                                                      IMG_UINT32 * pui32Free,
+                                                      IMG_UINT32 *
+                                                      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_ERROR eError = PVRSRV_OK;
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+       IMG_HANDLE hOSWrapMem;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+       if (psMemInfo->psKernelSyncInfo) {
+               eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+       }
+
+       if (psMemInfo->sMemBlk.psIntSysPAddr) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0,
+                         psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+       }
+
+       if (eError == PVRSRV_OK) {
+               eError = FreeDeviceMem(psMemInfo);
+       }
+
+       if (hOSWrapMem) {
+               OSReleasePhysPageAddr(hOSWrapMem);
+       }
+
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
+                                                   PVRSRV_PER_PROCESS_DATA *
+                                                   psPerProc,
+                                                   IMG_UINT32 ui32ByteSize,
+                                                   IMG_UINT32 ui32PageOffset,
+                                                   IMG_BOOL bPhysContig,
+                                                   IMG_SYS_PHYADDR *
+                                                   psExtSysPAddr,
+                                                   IMG_VOID * pvLinAddr,
+                                                   PVRSRV_KERNEL_MEM_INFO **
+                                                   ppsMemInfo)
+{
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+       DEVICE_MEMORY_INFO *psDevMemoryInfo;
+       IMG_UINT32 ui32HostPageSize = HOST_PAGESIZE();
+       IMG_HANDLE hDevMemHeap, hDevMemContext;
+       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;
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+       PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+       if (pvLinAddr) {
+               IMG_UINT32 ui32PageCount;
+
+               ui32PageCount =
+                   HOST_PAGEALIGN(ui32ByteSize +
+                                  ui32PageOffset) / ui32HostPageSize;
+               pvPageAlignedCPUVAddr =
+                   (IMG_VOID *) ((IMG_UINT8 *) pvLinAddr - ui32PageOffset);
+
+               if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                              ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+                              (IMG_VOID **) & psIntSysPAddr,
+                              IMG_NULL) != 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;
+       } else {
+
+       }
+
+       psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+       hDevMemHeap =
+           psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
+                                               ui32MappingHeapID].hDevMemHeap;
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(PVRSRV_KERNEL_MEM_INFO),
+                      (IMG_VOID **) & psMemInfo, IMG_NULL) != 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));
+
+       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 ErrorExitPhase2;
+       }
+
+       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 ErrorExitPhase2;
+       }
+
+       psMemInfo->sMemBlk.hResItem =
+           ResManRegisterRes(psPerProc->hResManContext,
+                             RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0,
+                             UnwrapExtMemoryCallBack);
+
+       *ppsMemInfo = psMemInfo;
+
+       return PVRSRV_OK;
+
+ErrorExitPhase2:
+       if (psMemInfo) {
+               FreeDeviceMem(psMemInfo);
+       }
+
+       if (psIntSysPAddr) {
+               OSReleasePhysPageAddr(hOSWrapMem);
+       }
+
+ErrorExitPhase1:
+       if (psIntSysPAddr) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, 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_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       if (psMemInfo->sMemBlk.psIntSysPAddr) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0,
+                         psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+       }
+
+       return FreeDeviceMem(psMemInfo);
+}
+
+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_UINT32 ui32PageCount, ui32PageOffset;
+       IMG_UINT32 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;
+
+       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_UINT8 *) psSrcMemInfo->pvLinAddrKM -
+                         ui32PageOffset);
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+                      (IMG_VOID **) & psSysPAddr, IMG_NULL) != 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 - ui32PageOffset;
+       for (i = 0; i < ui32PageCount; i++) {
+               eError =
+                   BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "PVRSRVMapDeviceMemoryKM: Failed to retrieve page list from device"));
+                       goto ErrorExit;
+               }
+
+               psSysPAddr[i] =
+                   SysDevPAddrToSysPAddr(psDeviceNode->sDevId.eDeviceType,
+                                         sDevPAddr);
+
+               sDevVAddr.uiAddr += ui32HostPageSize;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(PVRSRV_KERNEL_MEM_INFO),
+                      (IMG_VOID **) & psMemInfo, IMG_NULL) != 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));
+
+       psMemBlock = &(psMemInfo->sMemBlk);
+
+       bBMError = BM_Wrap(psBuf->pMapping->pBMHeap,
+                          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;
+
+       psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+       psMemInfo->sMemBlk.hResItem =
+           ResManRegisterRes(psPerProc->hResManContext,
+                             RESMAN_TYPE_DEVICEMEM_MAPPING, psMemInfo, 0,
+                             UnmapDeviceMemoryCallBack);
+
+       *ppsDstMemInfo = psMemInfo;
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       if (psSysPAddr) {
+
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSysPAddr, IMG_NULL);
+       }
+
+       if (psMemInfo) {
+
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, 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_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       return FreeDeviceMem(psMemInfo);
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR IMG_CALLCONV
+PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+                            IMG_HANDLE hDeviceClassBuffer,
+                            PVRSRV_KERNEL_MEM_INFO ** ppsMemInfo,
+                            IMG_HANDLE * phOSMapInfo)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+       PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+       IMG_SYS_PHYADDR *psSysPAddr;
+       IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+       IMG_BOOL bPhysContig;
+       BM_CONTEXT *psBMContext;
+       DEVICE_MEMORY_INFO *psDevMemoryInfo;
+       IMG_HANDLE hDevMemHeap;
+       IMG_UINT32 ui32ByteSize;
+       IMG_UINT32 ui32Offset;
+       IMG_UINT32 ui32PageSize = HOST_PAGESIZE();
+       BM_HANDLE hBuffer;
+       PVRSRV_MEMBLK *psMemBlock;
+       IMG_BOOL bBMError;
+
+       if (!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVMapDeviceClassMemoryKM: invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER *) hDeviceClassBuffer;
+
+       eError =
+           psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->
+                                                 hExtDevice,
+                                                 psDeviceClassBuffer->
+                                                 hExtBuffer, &psSysPAddr,
+                                                 &ui32ByteSize, &pvCPUVAddr,
+                                                 phOSMapInfo, &bPhysContig);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVMapDeviceClassMemoryKM: unable to get buffer address"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       psBMContext = (BM_CONTEXT *) psDeviceClassBuffer->hDevMemContext;
+       psDevMemoryInfo = &psBMContext->psDeviceNode->sDevMemoryInfo;
+       hDevMemHeap =
+           psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
+                                               ui32MappingHeapID].hDevMemHeap;
+
+       ui32Offset = ((IMG_UINT32) pvCPUVAddr) & (ui32PageSize - 1);
+       pvPageAlignedCPUVAddr =
+           (IMG_VOID *) ((IMG_UINT8 *) pvCPUVAddr - ui32Offset);
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(PVRSRV_KERNEL_MEM_INFO),
+                      (IMG_VOID **) & psMemInfo, IMG_NULL) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block"));
+               return (PVRSRV_ERROR_OUT_OF_MEMORY);
+       }
+
+       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"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL);
+               return PVRSRV_ERROR_BAD_MAPPING;
+       }
+
+       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;
+
+       psMemInfo->sMemBlk.hResItem =
+           ResManRegisterRes(psPerProc->hResManContext,
+                             RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psMemInfo, 0,
+                             UnmapDeviceClassMemoryCallBack);
+
+       *ppsMemInfo = psMemInfo;
+
+       return PVRSRV_OK;
+}
diff --git a/pvr/env_data.h b/pvr/env_data.h
new file mode 100644 (file)
index 0000000..ecfaa59
--- /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 _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#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;
+       struct tasklet_struct sMISRTasklet;
+} ENV_DATA;
+
+#endif
diff --git a/pvr/event.c b/pvr/event.c
new file mode 100644 (file)
index 0000000..61bcc5a
--- /dev/null
@@ -0,0 +1,278 @@
+/**********************************************************************
+ *
+ * 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 AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#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/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"
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+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 DEBUG
+       unsigned int 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) != 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 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;
+
+       write_lock_bh(&psLinuxEventObjectList->sLock);
+       list_del(&psLinuxEventObject->sList);
+       write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+#if 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) != 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 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 =
+                   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)
+{
+       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);
+
+               if (psLinuxEventObject->ui32TimeStampPrevious !=
+                   atomic_read(&psLinuxEventObject->sTimeStamp)) {
+                       break;
+               }
+
+               LinuxUnLockMutex(&gPVRSRVLock);
+
+               ui32TimeOutJiffies = schedule_timeout(ui32TimeOutJiffies);
+
+#if DEBUG
+               psLinuxEventObject->ui32Stats++;
+#endif
+               LinuxLockMutex(&gPVRSRVLock);
+
+       } while (ui32TimeOutJiffies);
+
+       finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+       psLinuxEventObject->ui32TimeStampPrevious =
+           atomic_read(&psLinuxEventObject->sTimeStamp);
+
+       return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
diff --git a/pvr/event.h b/pvr/event.h
new file mode 100644 (file)
index 0000000..8d609bc
--- /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 
+ *
+ ******************************************************************************/
+
+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/pvr/handle.c b/pvr/handle.c
new file mode 100644 (file)
index 0000000..ddbb468
--- /dev/null
@@ -0,0 +1,1366 @@
+/**********************************************************************
+ *
+ * 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_SIZE       1
+#else
+#define        HANDLE_BLOCK_SIZE       256
+#endif
+
+#define        HANDLE_HASH_TAB_INIT_SIZE       32
+
+#define        INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+#define        INDEX_TO_HANDLE(psBase, idx) ((IMG_HANDLE)((idx) + 1))
+#define        HANDLE_TO_INDEX(psBase, hand) ((IMG_UINT32)(hand) - 1)
+
+#define INDEX_TO_HANDLE_PTR(psBase, i) (((psBase)->psHandleArray) + (i))
+#define        HANDLE_TO_HANDLE_PTR(psBase, h) (INDEX_TO_HANDLE_PTR(psBase, HANDLE_TO_INDEX(psBase, h)))
+
+#define        HANDLE_PTR_TO_INDEX(psBase, psHandle) ((psHandle) - ((psBase)->psHandleArray))
+#define        HANDLE_PTR_TO_HANDLE(psBase, psHandle) \
+       INDEX_TO_HANDLE(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle))
+
+#define        ROUND_UP_TO_MULTIPLE(a, b) ((((a) + (b) - 1) / (b)) * (b))
+
+#define        HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
+
+#define        SET_FLAG(v, f) ((void)((v) |= (f)))
+#define        CLEAR_FLAG(v, f) ((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)
+
+struct sHandleList {
+       IMG_UINT32 ui32Prev;
+       IMG_UINT32 ui32Next;
+       IMG_HANDLE hParent;
+};
+
+enum ePVRSRVInternalHandleFlag {
+       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 ui32PID;
+
+       IMG_UINT32 ui32Index;
+
+       struct sHandleList sChildren;
+
+       struct sHandleList sSiblings;
+};
+
+struct _PVRSRV_HANDLE_BASE_ {
+
+       IMG_HANDLE hBaseBlockAlloc;
+
+       IMG_UINT32 ui32PID;
+
+       IMG_HANDLE hHandBlockAlloc;
+
+       PRESMAN_ITEM psResManItem;
+
+       struct sHandle *psHandleArray;
+
+       HASH_TABLE *psHashTab;
+
+       IMG_UINT32 ui32FreeHandCount;
+
+       IMG_UINT32 ui32FirstFreeIndex;
+
+       IMG_UINT32 ui32TotalHandCount;
+
+       IMG_UINT32 ui32LastFreeIndexPlusOne;
+
+       IMG_UINT32 ui32HandBatchSize;
+
+       IMG_UINT32 ui32TotalHandCountPreBatch;
+
+       IMG_UINT32 ui32FirstBatchIndexPlusOne;
+
+       IMG_UINT32 ui32BatchHandAllocFailures;
+};
+
+enum eHandKey {
+       HAND_KEY_DATA = 0,
+       HAND_KEY_TYPE,
+       HAND_KEY_PARENT,
+       HAND_KEY_LEN
+};
+
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+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(PVRSRV_HANDLE_BASE * psBase,
+                           struct sHandle *psHandle)
+{
+       IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+
+       HandleListInit(ui32Parent, &psHandle->sChildren,
+                      INDEX_TO_HANDLE(psBase, ui32Parent));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitChildEntry)
+#endif
+static INLINE
+    IMG_VOID InitChildEntry(PVRSRV_HANDLE_BASE * psBase,
+                           struct sHandle *psHandle)
+{
+       HandleListInit(HANDLE_PTR_TO_INDEX(psBase, 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(PVRSRV_HANDLE_BASE * psBase, struct sHandle *psHandle)
+{
+       PVR_ASSERT(psHandle->sChildren.hParent ==
+                  HANDLE_PTR_TO_HANDLE(psBase, psHandle));
+
+       return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle),
+                                &psHandle->sChildren);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoParent)
+#endif
+static INLINE
+    IMG_BOOL NoParent(PVRSRV_HANDLE_BASE * psBase, struct sHandle *psHandle)
+{
+       if (HandleListIsEmpty
+           (HANDLE_PTR_TO_INDEX(psBase, 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 *)((char *)(INDEX_TO_HANDLE_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(psBase,
+                                                               ui32ParentIndex));
+
+       psEntry->ui32Prev = psIns->ui32Prev;
+       psIns->ui32Prev = ui32EntryIndex;
+       psEntry->ui32Next = ui32InsIndex;
+       psPrevIns->ui32Next = ui32EntryIndex;
+
+       psEntry->hParent = INDEX_TO_HANDLE(psBase, 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(psBase, psParent->sChildren.hParent);
+
+       PVR_ASSERT(ui32Parent ==
+                  (IMG_UINT32) HANDLE_PTR_TO_INDEX(psBase, psParent));
+
+       HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren,
+                              offsetof(struct sHandle, sChildren),
+                              HANDLE_PTR_TO_INDEX(psBase, 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(psBase,
+                                                                  psEntry->
+                                                                  hParent),
+                                                  uiParentOffset,
+                                                  uiEntryOffset);
+               struct sHandleList *psNext =
+                   LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next,
+                                                  HANDLE_TO_INDEX(psBase,
+                                                                  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(psBase, 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(psBase, psHead->hParent);
+
+       PVR_ASSERT(psHead->hParent != IMG_NULL);
+
+       for (ui32Index = psHead->ui32Next; ui32Index != ui32Parent;) {
+               struct sHandle *psHandle =
+                   INDEX_TO_HANDLE_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(psBase, 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_GENERIC;
+       }
+
+       psHandle = INDEX_TO_HANDLE_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_GENERIC;
+       }
+
+       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_GENERIC;
+       }
+
+       PVR_ASSERT(psBase->ui32PID == psHandle->ui32PID);
+
+       *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 FreeHandleArray(PVRSRV_HANDLE_BASE * psBase)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (psBase->psHandleArray != IMG_NULL) {
+               eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                  psBase->ui32TotalHandCount *
+                                  sizeof(struct sHandle),
+                                  psBase->psHandleArray,
+                                  psBase->hHandBlockAlloc);
+
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "FreeHandleArray: Error freeing memory (%d)",
+                                eError));
+               } else {
+                       psBase->psHandleArray = IMG_NULL;
+               }
+       }
+
+       return eError;
+}
+
+static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE * psBase,
+                              struct sHandle *psHandle)
+{
+       HAND_KEY aKey;
+       IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psBase->ui32PID == psHandle->ui32PID);
+
+       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(psBase, 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->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_PTR
+                          (psBase,
+                           psBase->ui32LastFreeIndexPlusOne -
+                           1)->ui32NextIndexPlusOne == 0);
+
+               INDEX_TO_HANDLE_PTR(psBase,
+                                   psBase->ui32LastFreeIndexPlusOne -
+                                   1)->ui32NextIndexPlusOne = ui32Index + 1;
+       }
+
+       PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
+
+       psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+
+       psBase->ui32FreeHandCount++;
+
+       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_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_NON_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)
+{
+       struct sHandle *psNewHandleArray;
+       IMG_HANDLE hNewHandBlockAlloc;
+       PVRSRV_ERROR eError;
+       struct sHandle *psHandle;
+       IMG_UINT32 ui32DeltaRounded =
+           ROUND_UP_TO_MULTIPLE(ui32Delta, HANDLE_BLOCK_SIZE);
+       IMG_UINT32 ui32NewTotalHandCount =
+           psBase->ui32TotalHandCount + ui32DeltaRounded;
+       ;
+
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                           ui32NewTotalHandCount * sizeof(struct sHandle),
+                           (IMG_PVOID *) & psNewHandleArray,
+                           &hNewHandBlockAlloc);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "IncreaseHandleArraySize: Couldn't allocate new handle array (%d)",
+                        eError));
+               return eError;
+       }
+
+       if (psBase->psHandleArray != IMG_NULL)
+               OSMemCopy(psNewHandleArray,
+                         psBase->psHandleArray,
+                         psBase->ui32TotalHandCount * sizeof(struct sHandle));
+
+       for (psHandle = psNewHandleArray + psBase->ui32TotalHandCount;
+            psHandle < psNewHandleArray + ui32NewTotalHandCount; psHandle++) {
+               psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+               psHandle->ui32NextIndexPlusOne = 0;
+       }
+
+       eError = FreeHandleArray(psBase);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       psBase->psHandleArray = psNewHandleArray;
+       psBase->hHandBlockAlloc = hNewHandBlockAlloc;
+
+       psBase->ui32FreeHandCount += ui32DeltaRounded;
+
+       if (psBase->ui32FirstFreeIndex == 0) {
+               PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+               psBase->ui32FirstFreeIndex = psBase->ui32TotalHandCount;
+       } else {
+               PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
+                   PVR_ASSERT(INDEX_TO_HANDLE_PTR
+                              (psBase,
+                               psBase->ui32LastFreeIndexPlusOne -
+                               1)->ui32NextIndexPlusOne == 0);
+
+               INDEX_TO_HANDLE_PTR(psBase,
+                                   psBase->ui32LastFreeIndexPlusOne -
+                                   1)->ui32NextIndexPlusOne =
+                   psBase->ui32TotalHandCount + 1;
+
+       }
+       psBase->ui32LastFreeIndexPlusOne = ui32NewTotalHandCount;
+
+       psBase->ui32TotalHandCount = ui32NewTotalHandCount;
+
+       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;
+       struct sHandle *psNewHandle;
+       IMG_HANDLE hHandle;
+       HAND_KEY aKey;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+       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)
+
+           ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+       psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
+
+       hHandle = INDEX_TO_HANDLE(psBase, 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_GENERIC;
+               }
+       }
+
+       psBase->ui32FreeHandCount--;
+
+       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;
+       }
+
+       psNewHandle->eType = eType;
+       psNewHandle->pvData = pvData;
+       psNewHandle->eInternalFlag = 0;
+       psNewHandle->eFlag = eFlag;
+       psNewHandle->ui32PID = psBase->ui32PID;
+       psNewHandle->ui32Index = ui32NewIndex;
+
+       InitParentList(psBase, psNewHandle);
+       PVR_ASSERT(NoChildren(psBase, psNewHandle));
+
+       InitChildEntry(psBase, psNewHandle);
+       PVR_ASSERT(NoParent(psBase, psNewHandle));
+
+       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_GENERIC;
+               }
+       }
+
+       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 PVRSRV_ERROR_GENERIC;
+       }
+
+       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_PTR
+                                               (psBase, hHandle)) == hParent);
+
+                       if (TEST_FLAG
+                           (psCHandle->eFlag & eFlag,
+                            PVRSRV_HANDLE_ALLOC_FLAG_SHARED)
+                           &&
+                           ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle))
+                           == hParent) {
+                               *phHandle = hHandle;
+                               goto exit_ok;
+                       }
+                       return PVRSRV_ERROR_GENERIC;
+               }
+       }
+
+       eError =
+           AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       psPHand = HANDLE_TO_HANDLE_PTR(psBase, hParent);
+
+       psCHand = HANDLE_TO_HANDLE_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) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVFindHandle: couldn't find handle"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       *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_GENERIC;
+               }
+       }
+
+       *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_GENERIC;
+       }
+
+       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_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_GENERIC;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE * psBase)
+{
+       return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
+}
+
+void PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE * psBase)
+{
+       (void)PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
+}
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE ** ppsBase,
+                                  IMG_UINT32 ui32PID)
+{
+       PVRSRV_HANDLE_BASE *psBase;
+       IMG_HANDLE hBlockAlloc;
+       PVRSRV_ERROR eError;
+
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                           sizeof(*psBase),
+                           (IMG_PVOID *) & psBase, &hBlockAlloc);
+       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"));
+               goto failure;
+       }
+
+       psBase->hBaseBlockAlloc = hBlockAlloc;
+       psBase->ui32PID = ui32PID;
+
+       *ppsBase = psBase;
+
+       return PVRSRV_OK;
+failure:
+       (void)PVRSRVFreeHandleBase(psBase);
+       return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE * psBase)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psBase != gpsKernelHandleBase);
+
+       eError = FreeHandleBase(psBase);
+
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
+
+       eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase, KERNEL_ID);
+
+       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;
+               }
+       }
+
+       return eError;
+}
+#else
+#endif
diff --git a/pvr/handle.h b/pvr/handle.h
new file mode 100644 (file)
index 0000000..cca1cfb
--- /dev/null
@@ -0,0 +1,369 @@
+/**********************************************************************
+ *
+ * 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;
+
+       typedef enum {
+
+               PVRSRV_HANDLE_ALLOC_FLAG_NONE = 0,
+
+               PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 1,
+
+               PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 2,
+
+               PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 4
+       } 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);
+
+       void PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE * psBase);
+
+       PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE ** ppsBase,
+                                          IMG_UINT32 ui32PID);
+
+       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 void PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE * psBase) {
+               PVR_UNREFERENCED_PARAMETER(psBase);
+       }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandleBase)
+#endif
+       static INLINE
+           PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE ** ppsBase,
+                                              IMG_UINT32 ui32PID) {
+               PVR_UNREFERENCED_PARAMETER(ui32PID);
+
+               *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) \
+       (void)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
+
+#define PVRSRVAllocSubHandleNR(psBase, phHandle, pvData, eType, eFlag, hParent) \
+       (void)PVRSRVAllocSubHandle(psBase, phHandle, pvData, eType, eFlag, hParent)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
diff --git a/pvr/hash.c b/pvr/hash.c
new file mode 100644 (file)
index 0000000..92acdeb
--- /dev/null
@@ -0,0 +1,384 @@
+/**********************************************************************
+ *
+ * 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 void
+_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);
+
+       uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);
+       pBucket->pNext = ppBucketTable[uIndex];
+       ppBucketTable[uIndex] = pBucket;
+}
+
+static void
+_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) {
+                       BUCKET *pNextBucket = pBucket->pNext;
+                       _ChainInsert(pHash, pBucket, ppNewTable, uNewSize);
+                       pBucket = pNextBucket;
+               }
+       }
+}
+
+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_OS_PAGEABLE_HEAP,
+                          sizeof(BUCKET *) * uNewSize,
+                          (IMG_PVOID *) & ppNewTable, IMG_NULL);
+               if (ppNewTable == IMG_NULL)
+                       return IMG_FALSE;
+
+               for (uIndex = 0; uIndex < uNewSize; uIndex++)
+                       ppNewTable[uIndex] = IMG_NULL;
+               _Rehash(pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable,
+                       uNewSize);
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, 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_OS_PAGEABLE_HEAP,
+                      sizeof(HASH_TABLE),
+                      (IMG_VOID **) & pHash, IMG_NULL) != 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_OS_PAGEABLE_HEAP,
+                  sizeof(BUCKET *) * pHash->uSize,
+                  (IMG_PVOID *) & pHash->ppBucketTable, IMG_NULL);
+
+       if (pHash->ppBucketTable == IMG_NULL) {
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 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);
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pHash->ppBucketTable,
+                         IMG_NULL);
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 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=%08X, pKey=%08X, v=0x%x", pHash,
+                pKey, v));
+
+       PVR_ASSERT(pHash != IMG_NULL);
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(BUCKET) + pHash->uKeySize,
+                      (IMG_VOID **) & pBucket, IMG_NULL) != PVRSRV_OK) {
+               return IMG_FALSE;
+       }
+
+       pBucket->v = v;
+       OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+       _ChainInsert(pHash, pBucket, pHash->ppBucketTable, pHash->uSize);
+       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=%08X, k=0x%x, v=0x%x", 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: Hash=%08X, pKey=%08X", pHash,
+                pKey));
+
+       PVR_ASSERT(pHash != IMG_NULL);
+
+       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_OS_PAGEABLE_HEAP,
+                                 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=%08X, pKey=%08X = 0x%x",
+                                pHash, pKey, v));
+                       return v;
+               }
+       }
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "HASH_Remove_Extended: Hash=%08X, pKey=%08X = 0x0 !!!!", pHash,
+                pKey));
+       return 0;
+}
+
+IMG_UINTPTR_T HASH_Remove(HASH_TABLE * pHash, IMG_UINTPTR_T k)
+{
+       PVR_DPF((PVR_DBG_MESSAGE, "HASH_Remove: Hash=%08X, k=0x%x", 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: Hash=%08X, pKey=%08X", pHash,
+                pKey));
+
+       PVR_ASSERT(pHash != IMG_NULL);
+
+       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=%08X, pKey=%08X = 0x%x",
+                                pHash, pKey, v));
+                       return v;
+               }
+       }
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "HASH_Retrieve: Hash=%08X, pKey=%08X = 0x0 !!!!", pHash,
+                pKey));
+       return 0;
+}
+
+IMG_UINTPTR_T HASH_Retrieve(HASH_TABLE * pHash, IMG_UINTPTR_T k)
+{
+       PVR_DPF((PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=%08X, k=0x%x", pHash,
+                k));
+       return HASH_Retrieve_Extended(pHash, &k);
+}
+
+#ifdef HASH_TRACE
+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/pvr/hash.h b/pvr/hash.h
new file mode 100644 (file)
index 0000000..59b7f0a
--- /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 _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
+       void HASH_Dump(HASH_TABLE * pHash);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/img_defs.h b/pvr/img_defs.h
new file mode 100644 (file)
index 0000000..5cc140c
--- /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 
+ *
+ ******************************************************************************/
+
+#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
+#define        INLINE                                  __inline
+#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__)
+
+#define IMG_CALLCONV
+#define IMG_INTERNAL   __attribute__ ((visibility ("hidden")))
+#define IMG_EXPORT
+#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
+
+#endif
diff --git a/pvr/img_types.h b/pvr/img_types.h
new file mode 100644 (file)
index 0000000..b0ec065
--- /dev/null
@@ -0,0 +1,110 @@
+/**********************************************************************
+ *
+ * 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__
+
+typedef unsigned int IMG_UINT, *IMG_PUINT;
+typedef signed int IMG_INT, *IMG_PINT;
+
+typedef unsigned char IMG_UINT8, *IMG_PUINT8;
+typedef unsigned char IMG_BYTE, *IMG_PBYTE;
+typedef signed char IMG_INT8, *IMG_PINT8;
+typedef char IMG_CHAR, *IMG_PCHAR;
+
+typedef unsigned short IMG_UINT16, *IMG_PUINT16;
+typedef signed short IMG_INT16, *IMG_PINT16;
+typedef unsigned long IMG_UINT32, *IMG_PUINT32;
+typedef signed long IMG_INT32, *IMG_PINT32;
+
+#if defined(LINUX)
+#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;
+
+typedef IMG_UINT32 IMG_UINTPTR_T;
+
+typedef IMG_PVOID IMG_HANDLE;
+
+typedef void **IMG_HVOID, *IMG_PHVOID;
+
+typedef IMG_UINT32 IMG_SIZE_T;
+
+#define IMG_NULL        0
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+typedef struct {
+       IMG_UINT32 uiAddr;
+} IMG_CPU_PHYADDR;
+
+typedef struct {
+       IMG_UINT32 uiAddr;
+} IMG_DEV_VIRTADDR;
+
+typedef struct {
+       IMG_UINT32 uiAddr;
+} IMG_DEV_PHYADDR;
+
+typedef struct {
+       IMG_UINT32 uiAddr;
+} IMG_SYS_PHYADDR;
+
+typedef struct _SYSTEM_ADDR_ {
+
+       IMG_UINT32 ui32PageCount;
+       union {
+
+               IMG_SYS_PHYADDR sContig;
+
+               IMG_SYS_PHYADDR asNonContig[1];
+       } u;
+} SYSTEM_ADDR;
+
+#include "img_defs.h"
+
+#endif
diff --git a/pvr/ioctldef.h b/pvr/ioctldef.h
new file mode 100644 (file)
index 0000000..c9ae96d
--- /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 __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/pvr/kernelbuffer.h b/pvr/kernelbuffer.h
new file mode 100644 (file)
index 0000000..cad6eec
--- /dev/null
@@ -0,0 +1,59 @@
+/**********************************************************************
+ *
+ * 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__
+
+typedef PVRSRV_ERROR(*PFN_OPEN_BC_DEVICE) (IMG_HANDLE *);
+typedef PVRSRV_ERROR(*PFN_CLOSE_BC_DEVICE) (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 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_REMOVE_BUFFER_DEV pfnPVRSRVRemoveBCDevice;
+
+} PVRSRV_BC_BUFFER2SRV_KMJTABLE, *PPVRSRV_BC_BUFFER2SRV_KMJTABLE;
+
+typedef IMG_BOOL(*PFN_BC_GET_PVRJTABLE) (PPVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+#endif
diff --git a/pvr/kerneldisplay.h b/pvr/kerneldisplay.h
new file mode 100644 (file)
index 0000000..2364dca
--- /dev/null
@@ -0,0 +1,144 @@
+/**********************************************************************
+ *
+ * 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__
+
+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_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;
+
+} 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, PVR_POWER_STATE,
+                                             PVR_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;
+} 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);
+
+#endif
diff --git a/pvr/mem.c b/pvr/mem.c
new file mode 100644 (file)
index 0000000..c959dcb
--- /dev/null
+++ b/pvr/mem.c
@@ -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 "services_headers.h"
+#include "sgxapi_km.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_UINT32 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) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+       ui32Flags |= PVRSRV_HAP_MULTI_PROCESS;
+       psKernelMemInfo->ui32Flags = ui32Flags;
+       psKernelMemInfo->ui32AllocSize = ui32Size;
+
+       if (OSAllocPages(psKernelMemInfo->ui32Flags,
+                        psKernelMemInfo->ui32AllocSize,
+                        &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)
+{
+       if (!psKernelMemInfo) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (psKernelMemInfo->sMemBlk.hResItem) {
+               ResManDissociateRes(psKernelMemInfo->sMemBlk.hResItem,
+                                   IMG_NULL);
+               psKernelMemInfo->sMemBlk.hResItem = IMG_NULL;
+       }
+
+       return PVRSRV_OK;
+}
diff --git a/pvr/metrics.c b/pvr/metrics.c
new file mode 100644 (file)
index 0000000..dab858c
--- /dev/null
@@ -0,0 +1,144 @@
+/**********************************************************************
+ *
+ * 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 "sgxapi_km.h"
+#include "metrics.h"
+
+#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 = (unsigned int)0xffffffff;
+
+       *TST_REG |= (unsigned char)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/pvr/metrics.h b/pvr/metrics.h
new file mode 100644 (file)
index 0000000..c41d735
--- /dev/null
@@ -0,0 +1,112 @@
+/**********************************************************************
+ *
+ * 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 unsigned char *) (psDevInfo->pvSOCRegsBaseKM))
+
+#define TCOR_2    ((volatile unsigned int *)  (psDevInfo->pvSOCRegsBaseKM+28))
+#define TCNT_2    ((volatile unsigned int *)  (psDevInfo->pvSOCRegsBaseKM+32))
+#define TCR_2     ((volatile unsigned short *)(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/pvr/mm.c b/pvr/mm.c
new file mode 100644 (file)
index 0000000..6a149bd
--- /dev/null
+++ b/pvr/mm.c
@@ -0,0 +1,1756 @@
+/**********************************************************************
+ *
+ * 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 AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#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 "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+
+#if defined(CONFIG_ARCH_OMAP)
+#define        PVR_FLUSH_CACHE_BEFORE_KMAP
+#endif
+
+#if defined(PVR_FLUSH_CACHE_BEFORE_KMAP)
+#include <asm/cacheflush.h>
+#endif
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#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_KMAP,
+       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;
+       unsigned long ulCpuPAddr;
+       IMG_VOID *pvPrivateData;
+       IMG_UINT32 ui32Bytes;
+       pid_t pid;
+       IMG_CHAR *pszFileName;
+       IMG_UINT32 ui32Line;
+
+       struct _DEBUG_MEM_ALLOC_REC *psNext;
+} 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,
+                                      unsigned long 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 off_t printMemoryRecords(char *buffer, size_t size, off_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;
+} 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 off_t printLinuxMemAreaRecords(char *buffer, size_t size, off_t off);
+#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)
+       {
+               int iStatus;
+               iStatus =
+                   CreateProcReadEntry("mem_areas", printLinuxMemAreaRecords);
+               if (iStatus != 0) {
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+       }
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       {
+               int iStatus;
+               iStatus = CreateProcReadEntry("meminfo", printMemoryRecords);
+               if (iStatus != 0) {
+                       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;
+}
+
+IMG_VOID LinuxMMCleanup(IMG_VOID)
+{
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+       {
+               DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord =
+                   g_LinuxMemAreaRecords, *psNextRecord;
+
+               if (g_LinuxMemAreaCount) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%ld bytes)",
+                                __FUNCTION__, g_LinuxMemAreaCount,
+                                g_LinuxMemAreaWaterMark));
+               }
+
+               while (psCurrentRecord) {
+                       LinuxMemArea *psLinuxMemArea;
+
+                       psNextRecord = psCurrentRecord->psNext;
+                       psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%ld bytes",
+                                __FUNCTION__, psCurrentRecord->psLinuxMemArea,
+                                LinuxMemAreaTypeToString(psCurrentRecord->
+                                                         psLinuxMemArea->
+                                                         eAreaType),
+                                psCurrentRecord->psLinuxMemArea->
+                                ui32ByteSize));
+
+                       LinuxMemAreaDeepFree(psLinuxMemArea);
+
+                       psCurrentRecord = psNextRecord;
+               }
+               RemoveProcEntry("mem_areas");
+       }
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       {
+               DEBUG_MEM_ALLOC_REC *psCurrentRecord =
+                   g_MemoryRecords, *psNextRecord;
+
+               while (psCurrentRecord) {
+                       psNextRecord = psCurrentRecord->psNext;
+                       PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+                                "type=%s "
+                                "CpuVAddr=%p "
+                                "CpuPAddr=0x%08lx, "
+                                "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;
+                       case DEBUG_MEM_ALLOC_TYPE_KMAP:
+                               KUnMapWrapper(psCurrentRecord->pvKey);
+                               break;
+                       default:
+                               PVR_ASSERT(0);
+                       }
+                       psCurrentRecord = psNextRecord;
+               }
+               RemoveProcEntry("meminfo");
+       }
+#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);
+       }
+#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);
+#endif
+       kfree(pvCpuVAddr);
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID
+DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+                      IMG_VOID * pvKey,
+                      IMG_VOID * pvCpuVAddr,
+                      unsigned long ulCpuPAddr,
+                      IMG_VOID * pvPrivateData,
+                      IMG_UINT32 ui32Bytes,
+                      IMG_CHAR * pszFileName, IMG_UINT32 ui32Line)
+{
+       DEBUG_MEM_ALLOC_REC *psRecord;
+
+       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;
+
+       psRecord->psNext = g_MemoryRecords;
+       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;
+               }
+       }
+}
+
+static IMG_VOID
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID * pvKey,
+                         IMG_CHAR * pszFileName, IMG_UINT32 ui32Line)
+{
+       DEBUG_MEM_ALLOC_REC **ppsCurrentRecord;
+
+       for (ppsCurrentRecord = &g_MemoryRecords;
+            *ppsCurrentRecord;
+            ppsCurrentRecord = &((*ppsCurrentRecord)->psNext)) {
+               if ((*ppsCurrentRecord)->eAllocType == eAllocType
+                   && (*ppsCurrentRecord)->pvKey == pvKey) {
+                       DEBUG_MEM_ALLOC_REC *psNextRecord;
+                       DEBUG_MEM_ALLOC_TYPE eAllocType;
+
+                       psNextRecord = (*ppsCurrentRecord)->psNext;
+                       eAllocType = (*ppsCurrentRecord)->eAllocType;
+                       g_WaterMarkData[eAllocType] -=
+                           (*ppsCurrentRecord)->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 -=
+                                   (*ppsCurrentRecord)->ui32Bytes;
+                       } else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+                                  || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO) {
+                               g_IOMemWaterMark -=
+                                   (*ppsCurrentRecord)->ui32Bytes;
+                       }
+
+                       kfree(*ppsCurrentRecord);
+                       *ppsCurrentRecord = psNextRecord;
+                       return;
+               }
+       }
+
+       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));
+}
+
+static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE
+                                                eAllocType)
+{
+       char *apszDebugMemoryRecordTypes[] = {
+               "KMALLOC",
+               "VMALLOC",
+               "ALLOC_PAGES",
+               "IOREMAP",
+               "IO",
+               "KMEM_CACHE_ALLOC",
+               "KMAP"
+       };
+       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:
+#if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+               PGProtFlags = pgprot_writecombine(PAGE_KERNEL);
+#else
+               PGProtFlags = pgprot_noncached(PAGE_KERNEL);
+#endif
+               break;
+       case PVRSRV_HAP_UNCACHED:
+               PGProtFlags = pgprot_noncached(PAGE_KERNEL);
+               break;
+       default:
+               PVR_DPF((PVR_DBG_ERROR,
+                        "VMAllocWrapper: unknown mapping flags=0x%08lx",
+                        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);
+       }
+#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);
+#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;
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+       DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+       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);
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID ReservePages(IMG_VOID * pvAddress, IMG_UINT32 ui32Length)
+{
+       IMG_VOID *pvPage;
+       IMG_VOID *pvEnd = pvAddress + ui32Length;
+
+       for (pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE) {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+               SetPageReserved(vmalloc_to_page(pvPage));
+#else
+               mem_map_reserve(vmalloc_to_page(pvPage));
+#endif
+       }
+}
+
+static IMG_VOID UnreservePages(IMG_VOID * pvAddress, IMG_UINT32 ui32Length)
+{
+       IMG_VOID *pvPage;
+       IMG_VOID *pvEnd = pvAddress + ui32Length;
+
+       for (pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE) {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+               ClearPageReserved(vmalloc_to_page(pvPage));
+#else
+               mem_map_unreserve(vmalloc_to_page(pvPage));
+#endif
+       }
+}
+#endif
+
+IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+                         IMG_UINT32 ui32Bytes,
+                         IMG_UINT32 ui32MappingFlags,
+                         IMG_CHAR * pszFileName, IMG_UINT32 ui32Line)
+{
+       IMG_VOID *pvIORemapCookie = IMG_NULL;
+
+       switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK) {
+       case PVRSRV_HAP_CACHED:
+#if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+               pvIORemapCookie =
+                   (IMG_VOID *) ioremap_cached(BasePAddr.uiAddr, ui32Bytes);
+#else
+               pvIORemapCookie =
+                   (IMG_VOID *) ioremap(BasePAddr.uiAddr, ui32Bytes);
+#endif
+               break;
+       case PVRSRV_HAP_WRITECOMBINE:
+#if defined(__arm__)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+               pvIORemapCookie =
+                   (IMG_VOID *) ioremap_nocache(BasePAddr.uiAddr, ui32Bytes);
+#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17))
+               pvIORemapCookie =
+                   (IMG_VOID *) __ioremap(BasePAddr.uiAddr, ui32Bytes,
+                                          L_PTE_BUFFERABLE);
+#else
+               pvIORemapCookie =
+                   (IMG_VOID *) __ioremap(BasePAddr.uiAddr, ui32Bytes,
+                                          L_PTE_BUFFERABLE, 1);
+#endif
+#endif
+#else
+#if defined(__i386__) && defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+               pvIORemapCookie =
+                   (IMG_VOID *) __ioremap(BasePAddr.uiAddr, ui32Bytes,
+                                          _PAGE_PCD);
+#else
+               pvIORemapCookie =
+                   (IMG_VOID *) ioremap_nocache(BasePAddr.uiAddr, ui32Bytes);
+#endif
+#endif
+               break;
+       case PVRSRV_HAP_UNCACHED:
+               pvIORemapCookie =
+                   (IMG_VOID *) ioremap_nocache(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);
+       }
+#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);
+#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;
+
+#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);
+}
+
+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 = bPhysContig;
+       if (bPhysContig) {
+               psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr =
+                   *pBasePAddr;
+       } else {
+               psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr =
+                   pBasePAddr;
+       }
+       psLinuxMemArea->ui32ByteSize = ui32Bytes;
+
+#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;
+
+#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_UINT32 i;
+
+       psLinuxMemArea = LinuxMemAreaStructAlloc();
+       if (!psLinuxMemArea) {
+               goto failed_area_alloc;
+       }
+
+       ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
+       pvPageList =
+           VMallocWrapper(sizeof(void *) * ui32PageCount, PVRSRV_HAP_CACHED);
+       if (!pvPageList) {
+               goto failed_vmalloc;
+       }
+
+       for (i = 0; i < ui32PageCount; i++) {
+               pvPageList[i] = alloc_pages(GFP_KERNEL, 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->ui32ByteSize = ui32Bytes;
+
+#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);
+       }
+       VFreeWrapper(pvPageList);
+failed_vmalloc:
+       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_UINT32 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;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList,
+                                 __FILE__, __LINE__);
+#endif
+
+       for (i = 0; i < 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);
+       }
+       VFreeWrapper(psLinuxMemArea->uData.sPageList.pvPageList);
+
+       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];
+               break;
+       case LINUX_MEM_AREA_VMALLOC:
+               pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+               pui8Addr += ui32ByteOffset;
+               return vmalloc_to_page(pui8Addr);
+               break;
+       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",
+                        LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
+               return NULL;
+       }
+}
+
+IMG_VOID *_KMapWrapper(struct page * psPage, IMG_CHAR * pszFileName,
+                      IMG_UINT32 ui32Line)
+{
+       IMG_VOID *pvRet;
+
+#if defined(PVR_FLUSH_CACHE_BEFORE_KMAP)
+
+       flush_cache_all();
+#endif
+
+       pvRet = kmap(psPage);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       if (pvRet) {
+               DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMAP,
+                                      psPage,
+                                      pvRet, 0, NULL, PAGE_SIZE, "unknown", 0);
+       }
+#endif
+
+       return pvRet;
+}
+
+IMG_VOID
+_KUnMapWrapper(struct page * psPage, IMG_CHAR * pszFileName,
+              IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMAP, psPage,
+                                 pszFileName, ui32Line);
+#endif
+
+       kunmap(psPage);
+}
+
+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
+                                int Flags,
+#endif
+                                IMG_CHAR * pszFileName, IMG_UINT32 ui32Line)
+{
+       IMG_VOID *pvRet;
+
+       pvRet = kmem_cache_alloc(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);
+#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);
+#endif
+
+       kmem_cache_free(psCache, pvObject);
+}
+
+const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache * 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;
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+       {
+               DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
+               psParentRecord =
+                   DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
+               DebugLinuxMemAreaRecordAdd(psLinuxMemArea,
+                                          psParentRecord->ui32Flags);
+       }
+#endif
+
+       return psLinuxMemArea;
+}
+
+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));
+       }
+}
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID
+DebugLinuxMemAreaRecordAdd(LinuxMemArea * psLinuxMemArea, IMG_UINT32 ui32Flags)
+{
+       DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
+       const char *pi8FlagsString;
+
+       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;
+               psNewRecord->psNext = g_LinuxMemAreaRecords;
+               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%08lx) associated with psLinuxMemArea @ 0x%08lx",
+                        __FUNCTION__, ui32Flags, psLinuxMemArea));
+
+       }
+}
+
+static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *
+                                                            psLinuxMemArea)
+{
+       DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+       for (psCurrentRecord = g_LinuxMemAreaRecords;
+            psCurrentRecord; psCurrentRecord = psCurrentRecord->psNext) {
+               if (psCurrentRecord->psLinuxMemArea == psLinuxMemArea) {
+                       return psCurrentRecord;
+               }
+       }
+       return NULL;
+}
+
+static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea * psLinuxMemArea)
+{
+       DEBUG_LINUX_MEM_AREA_REC **ppsCurrentRecord;
+
+       if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) {
+               g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
+       }
+       g_LinuxMemAreaCount--;
+
+       for (ppsCurrentRecord = &g_LinuxMemAreaRecords;
+            *ppsCurrentRecord;
+            ppsCurrentRecord = &((*ppsCurrentRecord)->psNext)) {
+               if ((*ppsCurrentRecord)->psLinuxMemArea == psLinuxMemArea) {
+                       DEBUG_LINUX_MEM_AREA_REC *psNextRecord;
+
+                       psNextRecord = (*ppsCurrentRecord)->psNext;
+                       kfree(*ppsCurrentRecord);
+                       *ppsCurrentRecord = psNextRecord;
+                       return;
+               }
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "%s: couldn't find an entry for psLinuxMemArea=%p\n",
+                __FUNCTION__, psLinuxMemArea));
+}
+#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);
+       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:
+               PVR_DPF((PVR_DBG_WARNING,
+                        "%s is meaningless for LinuxMemArea type (%d)",
+                        __FUNCTION__, psLinuxMemArea->eAreaType));
+               break;
+
+       default:
+               PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+                        __FUNCTION__, psLinuxMemArea->eAreaType));
+               break;
+       }
+       return IMG_FALSE;
+}
+
+LINUX_MEM_AREA_TYPE LinuxMemAreaRootType(LinuxMemArea * psLinuxMemArea)
+{
+       if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC) {
+               return LinuxMemAreaRootType(psLinuxMemArea->uData.sSubAlloc.
+                                           psParentLinuxMemArea);
+       } else {
+               return psLinuxMemArea->eAreaType;
+       }
+}
+
+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)
+static off_t printLinuxMemAreaRecords(char *buffer, size_t count, off_t off)
+{
+       DEBUG_LINUX_MEM_AREA_REC *psRecord;
+       off_t Ret;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       if (!off) {
+               if (count < 500) {
+                       Ret = 0;
+                       goto unlock_and_return;
+               }
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+               Ret = printAppend(buffer, count, 0,
+                                 "Number of Linux Memory Areas: %lu\n"
+                                 "At the current water mark these areas correspond to %lu bytes (excluding SUB areas)\n"
+                                 "At the highest water mark these areas corresponded to %lu 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
+               Ret = printAppend(buffer, count, 0,
+                                 "<mem_areas_header>\n"
+                                 "\t<count>%lu</count>\n"
+                                 "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%lu\"/>\n"
+                                 "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%lu\"/>\n"
+                                 "</mem_areas_header>\n",
+                                 g_LinuxMemAreaCount,
+                                 g_LinuxMemAreaWaterMark,
+                                 g_LinuxMemAreaHighWaterMark);
+#endif
+               goto unlock_and_return;
+       }
+
+       for (psRecord = g_LinuxMemAreaRecords; --off && psRecord;
+            psRecord = psRecord->psNext) ;
+       if (!psRecord) {
+               Ret = END_OF_FILE;
+               goto unlock_and_return;
+       }
+
+       if (count < 500) {
+               Ret = 0;
+               goto unlock_and_return;
+       }
+
+       Ret = printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                         "%8p       %-24s %8p %08lx %-8ld %-5u %08lx=(%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>%08lx</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)
+           );
+
+unlock_and_return:
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+       return Ret;
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static off_t printMemoryRecords(char *buffer, size_t count, off_t off)
+{
+       DEBUG_MEM_ALLOC_REC *psRecord;
+       off_t Ret;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       if (!off) {
+               if (count < 1000) {
+                       Ret = 0;
+                       goto unlock_and_return;
+               }
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+
+               Ret = printAppend(buffer, count, 0, "%-60s: %ld bytes\n",
+                                 "Current Water Mark of bytes allocated via kmalloc",
+                                 g_WaterMarkData
+                                 [DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Highest Water Mark of bytes allocated via kmalloc",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Current Water Mark of bytes allocated via vmalloc",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Highest Water Mark of bytes allocated via vmalloc",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Current Water Mark of bytes allocated via alloc_pages",
+                               g_WaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Highest Water Mark of bytes allocated via alloc_pages",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Current Water Mark of bytes allocated via ioremap",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Highest Water Mark of bytes allocated via ioremap",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Current Water Mark of bytes reserved for \"IO\" memory areas",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+                               g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Current Water Mark of bytes allocated via kmem_cache_alloc",
+                               g_WaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Current Water Mark of bytes mapped via kmap",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMAP]);
+               Ret =
+                   printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                               "Highest Water Mark of bytes mapped via kmap",
+                               g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMAP]);
+
+               Ret = printAppend(buffer, count, Ret, "\n");
+
+               Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                                 "The Current Water Mark for memory allocated from system RAM",
+                                 g_SysRAMWaterMark);
+               Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                                 "The Highest Water Mark for memory allocated from system RAM",
+                                 g_SysRAMHighWaterMark);
+               Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                                 "The Current Water Mark for memory allocated from IO memory",
+                                 g_IOMemWaterMark);
+               Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                                 "The Highest Water Mark for memory allocated from IO memory",
+                                 g_IOMemHighWaterMark);
+
+               Ret = printAppend(buffer, count, Ret, "\n");
+
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "Details for all known allocations:\n"
+                               "%-16s %-8s %-8s %-10s %-5s %-10s %s\n", "Type",
+                               "CpuVAddr", "CpuPAddr", "Bytes", "PID",
+                               "PrivateData", "Filename:Line");
+
+#else
+
+               Ret =
+                   printAppend(buffer, count, 0,
+                               "<meminfo>\n<meminfo_header>\n");
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%ld\"/>\n",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%ld\"/>\n",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%ld\"/>\n",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%ld\"/>\n",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%ld\"/>\n",
+                               g_WaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%ld\"/>\n",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%ld\"/>\n",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%ld\"/>\n",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%ld\"/>\n",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%ld\"/>\n",
+                               g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%ld\"/>\n",
+                               g_WaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%ld\"/>\n",
+                               g_HighWaterMarkData
+                               [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr12\" description=\"kmap_current\" bytes=\"%ld\"/>\n",
+                               g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMAP]);
+               Ret =
+                   printAppend(buffer, count, Ret,
+                               "<watermark key=\"mr13\" description=\"kmap_high\" bytes=\"%ld\"/>\n",
+                               g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMAP]);
+
+               Ret = printAppend(buffer, count, Ret, "\n");
+
+               Ret = printAppend(buffer, count, Ret,
+                                 "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%ld\"/>\n",
+                                 g_SysRAMWaterMark);
+               Ret = printAppend(buffer, count, Ret,
+                                 "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%ld\"/>\n",
+                                 g_SysRAMHighWaterMark);
+               Ret = printAppend(buffer, count, Ret,
+                                 "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%ld\"/>\n",
+                                 g_IOMemWaterMark);
+               Ret = printAppend(buffer, count, Ret,
+                                 "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%ld\"/>\n",
+                                 g_IOMemHighWaterMark);
+
+               Ret = printAppend(buffer, count, Ret, "</meminfo_header>\n");
+
+#endif
+
+               goto unlock_and_return;
+       }
+
+       if (count < 1000) {
+               Ret = 0;
+               goto unlock_and_return;
+       }
+
+       for (psRecord = g_MemoryRecords; --off && psRecord;
+            psRecord = psRecord->psNext) ;
+       if (!psRecord) {
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+               if (off == 0) {
+                       Ret = printAppend(buffer, count, 0, "</meminfo>\n");
+                       goto unlock_and_return;
+               }
+#endif
+               Ret = END_OF_FILE;
+               goto unlock_and_return;
+       }
+
+       if (psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE) {
+               Ret = printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                                 "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+                                 "<allocation>\n"
+                                 "\t<type>%s</type>\n"
+                                 "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                                 "\t<cpu_physical>%08lx</cpu_physical>\n"
+                                 "\t<bytes>%ld</bytes>\n"
+                                 "\t<pid>%d</pid>\n"
+                                 "\t<private>%s</private>\n"
+                                 "\t<filename>%s</filename>\n"
+                                 "\t<line>%ld</line>\n" "</allocation>\n",
+#endif
+                                 DebugMemAllocRecordTypeToString(psRecord->
+                                                                 eAllocType),
+                                 psRecord->pvCpuVAddr, psRecord->ulCpuPAddr,
+                                 psRecord->ui32Bytes, psRecord->pid, "NULL",
+                                 psRecord->pszFileName, psRecord->ui32Line);
+       } else {
+               Ret = printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                                 "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+                                 "<allocation>\n"
+                                 "\t<type>%s</type>\n"
+                                 "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                                 "\t<cpu_physical>%08lx</cpu_physical>\n"
+                                 "\t<bytes>%ld</bytes>\n"
+                                 "\t<pid>%d</pid>\n"
+                                 "\t<private>%s</private>\n"
+                                 "\t<filename>%s</filename>\n"
+                                 "\t<line>%ld</line>\n" "</allocation>\n",
+#endif
+                                 DebugMemAllocRecordTypeToString(psRecord->
+                                                                 eAllocType),
+                                 psRecord->pvCpuVAddr, psRecord->ulCpuPAddr,
+                                 psRecord->ui32Bytes, psRecord->pid,
+                                 KMemCacheNameWrapper(psRecord->pvPrivateData),
+                                 psRecord->pszFileName, psRecord->ui32Line);
+       }
+
+unlock_and_return:
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+       return Ret;
+}
+#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_UINT32 ui32Pos = 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 (%d)",
+                        __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 (%d)",
+                        __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
+       }
+
+       ui32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
+       sprintf(szFlags + ui32Pos, "%s", apszMapType[ui32MapTypeIndex]);
+
+       return szFlags;
+}
+#endif
diff --git a/pvr/mm.h b/pvr/mm.h
new file mode 100644 (file)
index 0000000..a0d0269
--- /dev/null
+++ b/pvr/mm.h
@@ -0,0 +1,288 @@
+/**********************************************************************
+ *
+ * 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__
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/mm.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
+
+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;
+               } sPageList;
+               struct _sSubAlloc {
+
+                       LinuxMemArea *psParentLinuxMemArea;
+                       IMG_UINT32 ui32ByteOffset;
+               } sSubAlloc;
+       } uData;
+
+       IMG_UINT32 ui32ByteSize;
+};
+
+#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);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMapWrapper(psPage) _KMapWrapper(psPage, __FILE__, __LINE__)
+#else
+#define KMapWrapper(psPage) _KMapWrapper(psPage, NULL, 0)
+#endif
+IMG_VOID *_KMapWrapper(struct page *psPage, IMG_CHAR * pszFileName,
+                      IMG_UINT32 ui32Line);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KUnMapWrapper(psPage) _KUnMapWrapper(psPage, __FILE__, __LINE__)
+#else
+#define KUnMapWrapper(psPage) _KUnMapWrapper(psPage, NULL, 0)
+#endif
+IMG_VOID _KUnMapWrapper(struct page *psPage, IMG_CHAR * pszFileName,
+                       IMG_UINT32 ui32Line);
+
+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);
+
+LINUX_MEM_AREA_TYPE LinuxMemAreaRootType(LinuxMemArea * psLinuxMemArea);
+
+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/pvr/mmap.c b/pvr/mmap.c
new file mode 100644 (file)
index 0000000..8c5b2e5
--- /dev/null
@@ -0,0 +1,689 @@
+/**********************************************************************
+ *
+ * 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 AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#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
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "mm.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "proc.h"
+#include "mutex.h"
+
+static PKV_OFFSET_STRUCT FindOffsetStructFromLinuxMemArea(LinuxMemArea *
+                                                         psLinuxMemArea);
+static IMG_UINT32 GetFirstFreePageAlignedNumber(void);
+static PKV_OFFSET_STRUCT FindOffsetStructByKVIndexAddress(IMG_VOID *
+                                                         pvVirtAddress,
+                                                         IMG_UINT32
+                                                         ui32ByteSize);
+static void DeterminUsersSizeAndByteOffset(IMG_VOID * pvKVIndexAddress,
+                                          LinuxMemArea * psLinuxMemArea,
+                                          IMG_UINT32 * pui32RealByteSize,
+                                          IMG_UINT32 * pui32ByteOffset);
+static PKV_OFFSET_STRUCT FindOffsetStructByMMapOffset(IMG_UINT32 ui32Offset);
+static IMG_BOOL DoMapToUser(LinuxMemArea * psLinuxMemArea,
+                           struct vm_area_struct *ps_vma,
+                           IMG_UINT32 ui32ByteOffset, IMG_UINT32 ui32Size);
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off);
+#endif
+
+static void MMapVOpen(struct vm_area_struct *ps_vma);
+static void MMapVClose(struct vm_area_struct *ps_vma);
+
+static struct vm_operations_struct MMapIOOps = {
+open:  MMapVOpen,
+close: MMapVClose
+};
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+static PKV_OFFSET_STRUCT g_psKVOffsetTable = 0;
+static LinuxKMemCache *g_psMemmapCache = 0;
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static IMG_UINT32 g_ui32RegisteredAreas = 0;
+static IMG_UINT32 g_ui32TotalByteSize = 0;
+#endif
+
+IMG_VOID PVRMMapInit(IMG_VOID)
+{
+       g_psKVOffsetTable = 0;
+
+       g_psMemmapCache =
+           KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
+       if (g_psMemmapCache) {
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+               CreateProcReadEntry("mmap", PrintMMapRegistrations);
+#endif
+       } else {
+               PVR_DPF((PVR_DBG_ERROR, "%s: failed to allocate kmem_cache",
+                        __FUNCTION__));
+       }
+}
+
+IMG_VOID PVRMMapCleanup(void)
+{
+       PKV_OFFSET_STRUCT psOffsetStruct;
+
+       if (!g_psMemmapCache)
+               return;
+
+       if (g_psKVOffsetTable) {
+               PVR_DPF((PVR_DBG_ERROR, "%s: BUG! g_psMemmapCache isn't empty!",
+                        __FUNCTION__));
+
+               for (psOffsetStruct = g_psKVOffsetTable; psOffsetStruct;
+                    psOffsetStruct = psOffsetStruct->psNext) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: BUG!: Un-registering mmapable area: psLinuxMemArea=0x%p, CpuPAddr=0x%08lx\n",
+                                __FUNCTION__, psOffsetStruct->psLinuxMemArea,
+                                LinuxMemAreaToCpuPAddr(psOffsetStruct->
+                                                       psLinuxMemArea,
+                                                       0).uiAddr));
+                       PVRMMapRemoveRegisteredArea(psOffsetStruct->
+                                                   psLinuxMemArea);
+               }
+       }
+
+       RemoveProcEntry("mmap");
+       KMemCacheDestroyWrapper(g_psMemmapCache);
+       g_psMemmapCache = NULL;
+       PVR_DPF((PVR_DBG_MESSAGE, "PVRMMapCleanup: KVOffsetTable deallocated"));
+}
+
+PVRSRV_ERROR
+PVRMMapRegisterArea(const IMG_CHAR * pszName,
+                   LinuxMemArea * psLinuxMemArea, IMG_UINT32 ui32AllocFlags)
+{
+       PKV_OFFSET_STRUCT psOffsetStruct;
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "%s(%s, psLinuxMemArea=%p, ui32AllocFlags=0x%8lx)",
+                __FUNCTION__, pszName, psLinuxMemArea, ui32AllocFlags));
+
+       psOffsetStruct = FindOffsetStructFromLinuxMemArea(psLinuxMemArea);
+       if (psOffsetStruct) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRMMapRegisterArea: psLinuxMemArea=%p is already registered",
+                        psOffsetStruct->psLinuxMemArea));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
+       if (!psOffsetStruct) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       psOffsetStruct->ui32MMapOffset = GetFirstFreePageAlignedNumber();
+       psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+       if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) {
+               psOffsetStruct->ui32AllocFlags = ui32AllocFlags;
+       } else {
+               PKV_OFFSET_STRUCT psParentOffsetStruct;
+               psParentOffsetStruct =
+                   FindOffsetStructFromLinuxMemArea(psLinuxMemArea->uData.
+                                                    sSubAlloc.
+                                                    psParentLinuxMemArea);
+               PVR_ASSERT(psParentOffsetStruct);
+               psOffsetStruct->ui32AllocFlags =
+                   psParentOffsetStruct->ui32AllocFlags;
+       }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+       psOffsetStruct->pszName = pszName;
+       psOffsetStruct->pid = current->pid;
+       psOffsetStruct->ui16Mapped = 0;
+       psOffsetStruct->ui16Faults = 0;
+
+       g_ui32RegisteredAreas++;
+       if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) {
+               g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
+       }
+#endif
+
+       psOffsetStruct->psNext = g_psKVOffsetTable;
+
+       g_psKVOffsetTable = psOffsetStruct;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea)
+{
+       PKV_OFFSET_STRUCT *ppsOffsetStruct, psOffsetStruct;
+
+       for (ppsOffsetStruct = &g_psKVOffsetTable;
+            (psOffsetStruct = *ppsOffsetStruct);
+            ppsOffsetStruct = &(*ppsOffsetStruct)->psNext) {
+               if (psOffsetStruct->psLinuxMemArea == psLinuxMemArea) {
+                       break;
+               }
+       }
+
+       if (!psOffsetStruct) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Registration for psLinuxMemArea = 0x%p not found",
+                        __FUNCTION__, psLinuxMemArea));
+               return PVRSRV_ERROR_BAD_MAPPING;
+       }
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+       if (psOffsetStruct->ui16Mapped) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Unregistering still-mapped area! (psLinuxMemArea=0x%p)\n",
+                        __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+               return PVRSRV_ERROR_BAD_MAPPING;
+       }
+
+       g_ui32RegisteredAreas--;
+
+       if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) {
+               g_ui32TotalByteSize -=
+                   psOffsetStruct->psLinuxMemArea->ui32ByteSize;
+       }
+#endif
+
+       PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+                "psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __FUNCTION__,
+                psOffsetStruct->psLinuxMemArea,
+                LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0)));
+
+       *ppsOffsetStruct = psOffsetStruct->psNext;
+
+       KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
+
+       return PVRSRV_OK;
+}
+
+static PKV_OFFSET_STRUCT
+FindOffsetStructFromLinuxMemArea(LinuxMemArea * psLinuxMemArea)
+{
+       PKV_OFFSET_STRUCT psOffsetStruct = NULL;
+
+       for (psOffsetStruct = g_psKVOffsetTable; psOffsetStruct;
+            psOffsetStruct = psOffsetStruct->psNext) {
+               if (psOffsetStruct->psLinuxMemArea == psLinuxMemArea) {
+                       return psOffsetStruct;
+               }
+       }
+       return NULL;
+}
+
+static IMG_UINT32 GetFirstFreePageAlignedNumber(void)
+{
+       PKV_OFFSET_STRUCT psCurrentRec;
+       IMG_UINT32 ui32CurrentPageOffset;
+
+       if (!g_psKVOffsetTable) {
+               return 0;
+       }
+
+       psCurrentRec = g_psKVOffsetTable;
+       ui32CurrentPageOffset = (g_psKVOffsetTable->ui32MMapOffset);
+
+       while (psCurrentRec) {
+               if (ui32CurrentPageOffset != (psCurrentRec->ui32MMapOffset)) {
+                       return ui32CurrentPageOffset;
+               }
+               psCurrentRec = psCurrentRec->psNext;
+               ui32CurrentPageOffset += PAGE_SIZE;
+       }
+
+       return g_psKVOffsetTable->ui32MMapOffset + PAGE_SIZE;
+}
+
+PVRSRV_ERROR
+PVRMMapKVIndexAddressToMMapData(IMG_VOID * pvKVIndexAddress,
+                               IMG_UINT32 ui32Size,
+                               IMG_UINT32 * pui32MMapOffset,
+                               IMG_UINT32 * pui32ByteOffset,
+                               IMG_UINT32 * pui32RealByteSize)
+{
+       PKV_OFFSET_STRUCT psOffsetStruct;
+
+       psOffsetStruct =
+           FindOffsetStructByKVIndexAddress(pvKVIndexAddress, ui32Size);
+       if (!psOffsetStruct) {
+               return PVRSRV_ERROR_BAD_MAPPING;
+       }
+
+       *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+
+       DeterminUsersSizeAndByteOffset(pvKVIndexAddress,
+                                      psOffsetStruct->psLinuxMemArea,
+                                      pui32RealByteSize, pui32ByteOffset);
+
+       return PVRSRV_OK;
+}
+
+static PKV_OFFSET_STRUCT
+FindOffsetStructByKVIndexAddress(IMG_VOID * pvKVIndexAddress,
+                                IMG_UINT32 ui32ByteSize)
+{
+       PKV_OFFSET_STRUCT psOffsetStruct;
+       IMG_UINT8 *pui8CpuVAddr;
+       IMG_UINT8 *pui8IndexCpuVAddr = (IMG_UINT8 *) pvKVIndexAddress;
+
+       for (psOffsetStruct = g_psKVOffsetTable; psOffsetStruct;
+            psOffsetStruct = psOffsetStruct->psNext) {
+               LinuxMemArea *psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+
+               switch (psLinuxMemArea->eAreaType) {
+               case LINUX_MEM_AREA_IOREMAP:
+                       pui8CpuVAddr =
+                           psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
+                       break;
+               case LINUX_MEM_AREA_VMALLOC:
+                       pui8CpuVAddr =
+                           psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+                       break;
+               case LINUX_MEM_AREA_EXTERNAL_KV:
+                       pui8CpuVAddr =
+                           psLinuxMemArea->uData.sExternalKV.pvExternalKV;
+                       break;
+               default:
+                       pui8CpuVAddr = IMG_NULL;
+                       break;
+               }
+
+               if (pui8CpuVAddr) {
+                       if (pui8IndexCpuVAddr >= pui8CpuVAddr
+                           && (pui8IndexCpuVAddr + ui32ByteSize) <=
+                           (pui8CpuVAddr + psLinuxMemArea->ui32ByteSize)) {
+                               return psOffsetStruct;
+                       } else {
+                               pui8CpuVAddr = NULL;
+                       }
+               }
+
+               if (pvKVIndexAddress == psOffsetStruct->psLinuxMemArea) {
+                       if (psLinuxMemArea->eAreaType ==
+                           LINUX_MEM_AREA_SUB_ALLOC) {
+                               PVR_ASSERT(psLinuxMemArea->uData.sSubAlloc.
+                                          psParentLinuxMemArea->eAreaType !=
+                                          LINUX_MEM_AREA_SUB_ALLOC);
+                       }
+                       return psOffsetStruct;
+               }
+       }
+       printk(KERN_ERR "%s: Failed to find offset struct (KVAddress=%p)\n",
+              __FUNCTION__, pvKVIndexAddress);
+       return NULL;
+}
+
+static void
+DeterminUsersSizeAndByteOffset(IMG_VOID * pvKVIndexAddress,
+                              LinuxMemArea * psLinuxMemArea,
+                              IMG_UINT32 * pui32RealByteSize,
+                              IMG_UINT32 * pui32ByteOffset)
+{
+       IMG_UINT8 *pui8StartVAddr = NULL;
+       IMG_UINT8 *pui8IndexCpuVAddr = (IMG_UINT8 *) pvKVIndexAddress;
+       IMG_UINT32 ui32PageAlignmentOffset = 0;
+       IMG_CPU_PHYADDR CpuPAddr;
+
+       CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+       ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+
+       if (pvKVIndexAddress != psLinuxMemArea &&
+           (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP
+            || psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC
+            || psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV)) {
+               pui8StartVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+               *pui32ByteOffset =
+                   (pui8IndexCpuVAddr - pui8StartVAddr) +
+                   ui32PageAlignmentOffset;
+       } else {
+               *pui32ByteOffset = ui32PageAlignmentOffset;
+       }
+
+       *pui32RealByteSize =
+           PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma)
+{
+       unsigned long ulBytes;
+       PKV_OFFSET_STRUCT psCurrentRec = NULL;
+       int iRetVal = 0;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       ulBytes = ps_vma->vm_end - ps_vma->vm_start;
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "%s: Recieved mmap(2) request with a ui32MMapOffset=0x%08lx,"
+                " and ui32ByteSize=%ld(0x%08lx)\n", __FUNCTION__,
+                PFN_TO_PHYS(ps_vma->vm_pgoff), ulBytes, ulBytes));
+
+       if ((ps_vma->vm_flags & VM_WRITE) && !(ps_vma->vm_flags & VM_SHARED)
+           ) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRMMap: Error - Cannot mmap non-shareable writable areas."));
+               iRetVal = -EINVAL;
+               goto unlock_and_return;
+       }
+
+       psCurrentRec =
+           FindOffsetStructByMMapOffset(PFN_TO_PHYS(ps_vma->vm_pgoff));
+       if (!psCurrentRec) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRMMap: Error - Attempted to mmap unregistered area at vm_pgoff=%ld",
+                        ps_vma->vm_pgoff));
+               iRetVal = -EINVAL;
+               goto unlock_and_return;
+       }
+       PVR_DPF((PVR_DBG_MESSAGE, "%s: > psCurrentRec->psLinuxMemArea=%p\n",
+                __FUNCTION__, psCurrentRec->psLinuxMemArea));
+
+       ps_vma->vm_flags |= VM_RESERVED;
+       ps_vma->vm_flags |= VM_IO;
+
+       ps_vma->vm_flags |= VM_DONTEXPAND;
+
+       ps_vma->vm_private_data = (void *)psCurrentRec;
+
+       switch (psCurrentRec->ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK) {
+       case PVRSRV_HAP_CACHED:
+
+               break;
+       case PVRSRV_HAP_WRITECOMBINE:
+#if defined(__arm__) || defined(__sh__)
+               ps_vma->vm_page_prot =
+                   pgprot_writecombine(ps_vma->vm_page_prot);
+#else
+#if defined(__i386__)
+               ps_vma->vm_page_prot = pgprot_noncached(ps_vma->vm_page_prot);
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+
+               if (psCurrentRec->psLinuxMemArea->eAreaType ==
+                   LINUX_MEM_AREA_IOREMAP
+                   || psCurrentRec->psLinuxMemArea->eAreaType ==
+                   LINUX_MEM_AREA_IO) {
+                       ps_vma->vm_page_prot =
+                           __pgprot(pgprot_val(ps_vma->vm_page_prot) &=
+                                    ~_PAGE_PWT);
+               }
+#endif
+
+#else
+               ps_vma->vm_page_prot = pgprot_noncached(ps_vma->vm_page_prot);
+#error  Unsupported architecture!
+#endif
+#endif
+               break;
+       case PVRSRV_HAP_UNCACHED:
+               ps_vma->vm_page_prot = pgprot_noncached(ps_vma->vm_page_prot);
+               break;
+       default:
+               PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type",
+                        __FUNCTION__));
+       }
+
+       ps_vma->vm_ops = &MMapIOOps;
+
+       if (!DoMapToUser(psCurrentRec->psLinuxMemArea, ps_vma, 0, ulBytes)) {
+               iRetVal = -EAGAIN;
+               goto unlock_and_return;
+       }
+
+       MMapVOpen(ps_vma);
+
+       PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+                __FUNCTION__, ps_vma->vm_pgoff));
+
+unlock_and_return:
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+
+       return iRetVal;
+}
+
+static PKV_OFFSET_STRUCT FindOffsetStructByMMapOffset(IMG_UINT32 ui32MMapOffset)
+{
+       PKV_OFFSET_STRUCT psOffsetStruct;
+
+       for (psOffsetStruct = g_psKVOffsetTable; psOffsetStruct;
+            psOffsetStruct = psOffsetStruct->psNext) {
+               if (psOffsetStruct->ui32MMapOffset == ui32MMapOffset) {
+                       return psOffsetStruct;
+               }
+       }
+       return 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(psLinuxMemArea->uData.sSubAlloc.
+                                  psParentLinuxMemArea, ps_vma,
+                                  psLinuxMemArea->uData.sSubAlloc.
+                                  ui32ByteOffset + ui32ByteOffset,
+                                  ui32ByteSize);
+       }
+
+       PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+#if defined (__sparc__)
+
+#error "SPARC not supported"
+#endif
+
+       if (LinuxMemAreaPhysIsContig(psLinuxMemArea)) {
+
+               unsigned long pfn =
+                   LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset);
+
+               int result =
+                   IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, pfn,
+                                      ui32ByteSize, ps_vma->vm_page_prot);
+               if (result != 0) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Error - Failed to map contiguous physical address range (%d)",
+                                __FUNCTION__, result));
+                       return IMG_FALSE;
+               }
+       } else {
+
+               unsigned long ulVMAPos = ps_vma->vm_start;
+               IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+               IMG_UINT32 ui32PA;
+
+               for (ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd;
+                    ui32PA += PAGE_SIZE) {
+                       unsigned long pfn =
+                           LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+                       int result =
+                           REMAP_PFN_RANGE(ps_vma, ulVMAPos, pfn, PAGE_SIZE,
+                                           ps_vma->vm_page_prot);
+                       if (result != 0) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Error - Failed to map discontiguous physical address range (%d)",
+                                        __FUNCTION__, result));
+                               return IMG_FALSE;
+                       }
+                       ulVMAPos += PAGE_SIZE;
+               }
+       }
+
+       return IMG_TRUE;
+}
+
+static void MMapVOpen(struct vm_area_struct *ps_vma)
+{
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+       PKV_OFFSET_STRUCT psOffsetStruct =
+           (PKV_OFFSET_STRUCT) ps_vma->vm_private_data;
+       PVR_ASSERT(psOffsetStruct != IMG_NULL)
+           psOffsetStruct->ui16Mapped++;
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "%s: psLinuxMemArea=%p, KVAddress=%p MMapOffset=%ld, ui16Mapped=%d",
+                __FUNCTION__,
+                psOffsetStruct->psLinuxMemArea,
+                LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+                psOffsetStruct->ui32MMapOffset, psOffsetStruct->ui16Mapped));
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+       MOD_INC_USE_COUNT;
+#endif
+}
+
+static void MMapVClose(struct vm_area_struct *ps_vma)
+{
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+       PKV_OFFSET_STRUCT psOffsetStruct =
+           (PKV_OFFSET_STRUCT) ps_vma->vm_private_data;
+       PVR_ASSERT(psOffsetStruct != IMG_NULL)
+           psOffsetStruct->ui16Mapped--;
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "%s: psLinuxMemArea=%p, CpuVAddr=%p ui32MMapOffset=%ld, ui16Mapped=%d",
+                __FUNCTION__,
+                psOffsetStruct->psLinuxMemArea,
+                LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+                psOffsetStruct->ui32MMapOffset, psOffsetStruct->ui16Mapped));
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+       MOD_DEC_USE_COUNT;
+#endif
+}
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off)
+{
+       PKV_OFFSET_STRUCT psOffsetStruct;
+       off_t Ret;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       if (!off) {
+               Ret = printAppend(buffer, size, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                                 "Allocations registered for mmap: %lu\n"
+                                 "In total these areas correspond to %lu bytes (excluding SUB areas)\n"
+                                 "psLinuxMemArea "
+                                 "CpuVAddr "
+                                 "CpuPAddr "
+                                 "MMapOffset "
+                                 "ByteLength "
+                                 "LinuxMemType             "
+                                 "Pid   Name     Mapped Flags\n",
+#else
+                                 "<mmap_header>\n"
+                                 "\t<count>%lu</count>\n"
+                                 "\t<bytes>%lu</bytes>\n" "</mmap_header>\n",
+#endif
+                                 g_ui32RegisteredAreas, g_ui32TotalByteSize);
+
+               goto unlock_and_return;
+       }
+
+       if (size < 135) {
+               Ret = 0;
+               goto unlock_and_return;
+       }
+
+       for (psOffsetStruct = g_psKVOffsetTable; --off && psOffsetStruct;
+            psOffsetStruct = psOffsetStruct->psNext) ;
+       if (!psOffsetStruct) {
+               Ret = END_OF_FILE;
+               goto unlock_and_return;
+       }
+
+       Ret = printAppend(buffer, size, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                         "%-8p       %-8p %08lx %08lx   %-8ld   %-24s %-5d %-8s %-5u  %08lx(%s)\n",
+#else
+                         "<mmap_record>\n"
+                         "\t<pointer>%-8p</pointer>\n"
+                         "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                         "\t<cpu_physical>%08lx</cpu_physical>\n"
+                         "\t<mmap_offset>%08lx</mmap_offset>\n"
+                         "\t<bytes>%-8ld</bytes>\n"
+                         "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+                         "\t<pid>%-5d</pid>\n"
+                         "\t<name>%-8s</name>\n"
+                         "\t<mapping_count>%-5u</mapping_count>\n"
+                         "\t<flags>%08lx</flags>\n"
+                         "\t<flags_string>%s</flags_string>\n"
+                         "</mmap_record>\n",
+#endif
+                         psOffsetStruct->psLinuxMemArea,
+                         LinuxMemAreaToCpuVAddr(psOffsetStruct->
+                                                psLinuxMemArea),
+                         LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea,
+                                                0).uiAddr,
+                         psOffsetStruct->ui32MMapOffset,
+                         psOffsetStruct->psLinuxMemArea->ui32ByteSize,
+                         LinuxMemAreaTypeToString(psOffsetStruct->
+                                                  psLinuxMemArea->eAreaType),
+                         psOffsetStruct->pid, psOffsetStruct->pszName,
+                         psOffsetStruct->ui16Mapped,
+                         psOffsetStruct->ui32AllocFlags,
+                         HAPFlagsToString(psOffsetStruct->ui32AllocFlags));
+
+unlock_and_return:
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+       return Ret;
+}
+#endif
diff --git a/pvr/mmap.h b/pvr/mmap.h
new file mode 100644 (file)
index 0000000..0bebc53
--- /dev/null
@@ -0,0 +1,70 @@
+/**********************************************************************
+ *
+ * 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 "mm.h"
+
+typedef struct KV_OFFSET_STRUCT_TAG {
+
+       IMG_UINT32 ui32MMapOffset;
+
+       LinuxMemArea *psLinuxMemArea;
+
+       IMG_UINT32 ui32AllocFlags;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+       pid_t pid;
+       const IMG_CHAR *pszName;
+       IMG_UINT16 ui16Mapped;
+       IMG_UINT16 ui16Faults;
+#endif
+
+       struct KV_OFFSET_STRUCT_TAG *psNext;
+} KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+IMG_VOID PVRMMapInit(void);
+
+IMG_VOID PVRMMapCleanup(void);
+
+PVRSRV_ERROR PVRMMapRegisterArea(const IMG_CHAR * pszName,
+                                LinuxMemArea * psLinuxMemArea,
+                                IMG_UINT32 ui32AllocFlags);
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea);
+
+PVRSRV_ERROR PVRMMapKVIndexAddressToMMapData(IMG_VOID * pvKVIndexAddress,
+                                            IMG_UINT32 ui32Size,
+                                            IMG_UINT32 * pui32MMapOffset,
+                                            IMG_UINT32 * pui32ByteOffset,
+                                            IMG_UINT32 * pui32RealByteSize);
+
+int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma);
+
+#endif
diff --git a/pvr/mmu.c b/pvr/mmu.c
new file mode 100644 (file)
index 0000000..17c4a1f
--- /dev/null
+++ b/pvr/mmu.c
@@ -0,0 +1,1926 @@
+/**********************************************************************
+ *
+ * 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"
+
+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[1024];
+
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+
+       struct _MMU_CONTEXT_ *psNext;
+};
+
+struct _MMU_HEAP_ {
+       MMU_CONTEXT *psMMUContext;
+
+       IMG_UINT32 ui32PTBaseIndex;
+       IMG_UINT32 ui32PTPageCount;
+       IMG_UINT32 ui32PTEntryCount;
+
+       RA_ARENA *psVMArena;
+
+       DEV_ARENA_DESCRIPTOR *psDevArena;
+};
+
+#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 void PageTest(void *pMem, IMG_DEV_PHYADDR sDevPAddr);
+#endif
+
+#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(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(EUR_CR_BIF_CTRL, 0);
+}
+#endif
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+       psDevInfo->ui32CacheControl |= SGX_BIF_INVALIDATE_PDCACHE;
+}
+
+IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+       psDevInfo->ui32CacheControl |= SGX_BIF_INVALIDATE_PTCACHE;
+}
+
+static IMG_BOOL _AllocPageTables(MMU_HEAP * pMMUHeap)
+{
+       PVR_DPF((PVR_DBG_MESSAGE, "_AllocPageTables()"));
+
+       PVR_ASSERT(pMMUHeap != IMG_NULL);
+       PVR_ASSERT(HOST_PAGESIZE() == SGX_MMU_PAGE_SIZE);
+
+       if (pMMUHeap == IMG_NULL) {
+               PVR_DPF((PVR_DBG_ERROR, "_AllocPageTables: invalid parameter"));
+               return IMG_FALSE;
+       }
+
+       pMMUHeap->ui32PTEntryCount =
+           pMMUHeap->psDevArena->ui32Size >> SGX_MMU_PAGE_SHIFT;
+
+       pMMUHeap->ui32PTBaseIndex =
+           (pMMUHeap->psDevArena->BaseDevVAddr.
+            uiAddr & (SGX_MMU_PD_MASK | SGX_MMU_PT_MASK)) >>
+           SGX_MMU_PAGE_SHIFT;
+
+       pMMUHeap->ui32PTPageCount =
+           (pMMUHeap->ui32PTEntryCount + SGX_MMU_PT_SIZE -
+            1) >> SGX_MMU_PT_SHIFT;
+
+       return IMG_TRUE;
+}
+
+static IMG_VOID
+_DeferredFreePageTable(MMU_HEAP * pMMUHeap, IMG_UINT32 ui32PTIndex)
+{
+       IMG_UINT32 *pui32PDEntry;
+       IMG_UINT32 i;
+       IMG_UINT32 ui32PDIndex;
+       SYS_DATA *psSysData;
+       MMU_PT_INFO **ppsPTInfoList;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "_DeferredFreePageTables: ERROR call to SysAcquireData failed"));
+               return;
+       }
+
+       ui32PDIndex =
+           pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+                                                         SGX_MMU_PT_SHIFT);
+
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+       {
+
+               PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL
+                          || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount ==
+                          0);
+       }
+
+       PDUMPCOMMENT("Free page table (page count == %08X)",
+                    pMMUHeap->ui32PTPageCount);
+       if (ppsPTInfoList[ui32PTIndex]
+           && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr) {
+               PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX,
+                                  ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr,
+                                  SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+       }
+
+       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_VALID;
+#else
+
+                               pui32PDEntry[ui32PTIndex] = 0;
+#endif
+
+                               PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+                                         (IMG_VOID *) &
+                                         pui32PDEntry[ui32PTIndex],
+                                         sizeof(IMG_UINT32), 0, IMG_FALSE,
+                                         PDUMP_PT_UNIQUETAG,
+                                         PDUMP_PT_UNIQUETAG);
+
+                               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_VALID;
+#else
+
+                       pui32PDEntry[ui32PTIndex] = 0;
+#endif
+
+                       PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+                                 (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->ui32PTEntryCount) && (i < 1024);
+                            i++) {
+                               pui32Tmp[i] = 0;
+                       }
+
+                       if (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->
+                           psLocalDevMemArena == IMG_NULL) {
+                               OSFreePages(PVRSRV_HAP_WRITECOMBINE |
+                                           PVRSRV_HAP_KERNEL_ONLY,
+                                           SGX_MMU_PAGE_SIZE,
+                                           ppsPTInfoList[ui32PTIndex]->
+                                           PTPageCpuVAddr,
+                                           ppsPTInfoList[ui32PTIndex]->
+                                           hPTPageOSMemHandle);
+                       } else {
+                               IMG_SYS_PHYADDR sSysPAddr;
+                               IMG_CPU_PHYADDR sCpuPAddr;
+
+                               sCpuPAddr =
+                                   OSMapLinToCPUPhys(ppsPTInfoList
+                                                     [ui32PTIndex]->
+                                                     PTPageCpuVAddr);
+                               sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+                               OSUnMapPhysToLin(ppsPTInfoList[ui32PTIndex]->
+                                                PTPageCpuVAddr,
+                                                SGX_MMU_PAGE_SIZE,
+                                                PVRSRV_HAP_WRITECOMBINE |
+                                                PVRSRV_HAP_KERNEL_ONLY,
+                                                ppsPTInfoList[ui32PTIndex]->
+                                                hPTPageOSMemHandle);
+
+                               RA_Free(pMMUHeap->psDevArena->
+                                       psDeviceMemoryHeapInfo->
+                                       psLocalDevMemArena, sSysPAddr.uiAddr,
+                                       IMG_FALSE);
+                       }
+
+                       pMMUHeap->ui32PTEntryCount -= i;
+               } else {
+
+                       pMMUHeap->ui32PTEntryCount -= 1024;
+               }
+
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         sizeof(MMU_PT_INFO),
+                         ppsPTInfoList[ui32PTIndex], IMG_NULL);
+               ppsPTInfoList[ui32PTIndex] = IMG_NULL;
+       } else {
+
+               pMMUHeap->ui32PTEntryCount -= 1024;
+       }
+
+       PDUMPCOMMENT("Finished free page table (page count == %08X)",
+                    pMMUHeap->ui32PTPageCount);
+}
+
+static IMG_VOID _DeferredFreePageTables(MMU_HEAP * pMMUHeap)
+{
+       IMG_UINT32 i;
+
+       for (i = 0; i < pMMUHeap->ui32PTPageCount; i++) {
+               _DeferredFreePageTable(pMMUHeap, i);
+       }
+       MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+}
+
+static IMG_BOOL
+_DeferredAllocPagetables(MMU_HEAP * pMMUHeap, IMG_DEV_VIRTADDR DevVAddr,
+                        IMG_UINT32 ui32Size)
+{
+       IMG_UINT32 ui32PTPageCount;
+       IMG_UINT32 ui32PDIndex;
+       IMG_UINT32 i;
+       IMG_UINT32 *pui32PDEntry;
+       MMU_PT_INFO **ppsPTInfoList;
+       SYS_DATA *psSysData;
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
+       PVR_ASSERT(DevVAddr.uiAddr < (1 << SGX_FEATURE_ADDRESS_SPACE_SIZE));
+#endif
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               return IMG_FALSE;
+       }
+
+       ui32PDIndex =
+           DevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+       ui32PTPageCount =
+           (DevVAddr.uiAddr + ui32Size +
+            (1 << (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT)) - 1)
+           >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+       ui32PTPageCount -= ui32PDIndex;
+
+       pui32PDEntry = (IMG_UINT32 *) pMMUHeap->psMMUContext->pvPDCpuVAddr;
+       pui32PDEntry += ui32PDIndex;
+
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+       PDUMPCOMMENT("Alloc page table (page count == %08X)", ui32PTPageCount);
+       PDUMPCOMMENT("Page directory mods (page count == %08X)",
+                    ui32PTPageCount);
+
+       for (i = 0; i < ui32PTPageCount; i++) {
+               if (ppsPTInfoList[i] == IMG_NULL) {
+                       OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                  sizeof(MMU_PT_INFO),
+                                  (IMG_VOID **) & ppsPTInfoList[i], IMG_NULL);
+                       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_CPU_PHYADDR sCpuPAddr;
+                       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 (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->
+                           psLocalDevMemArena == IMG_NULL) {
+                               if (OSAllocPages
+                                   (PVRSRV_HAP_WRITECOMBINE |
+                                    PVRSRV_HAP_KERNEL_ONLY, SGX_MMU_PAGE_SIZE,
+                                    (IMG_VOID **) & ppsPTInfoList[i]->
+                                    PTPageCpuVAddr,
+                                    &ppsPTInfoList[i]->hPTPageOSMemHandle) !=
+                                   PVRSRV_OK) {
+                                       PVR_DPF((PVR_DBG_ERROR,
+                                                "_DeferredAllocPagetables: ERROR call to OSAllocPages failed"));
+                                       return IMG_FALSE;
+                               }
+
+                               if (ppsPTInfoList[i]->PTPageCpuVAddr) {
+                                       sCpuPAddr =
+                                           OSMapLinToCPUPhys(ppsPTInfoList[i]->
+                                                             PTPageCpuVAddr);
+                               } else {
+
+                                       sCpuPAddr =
+                                           OSMemHandleToCpuPAddr(ppsPTInfoList
+                                                                 [i]->
+                                                                 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,
+                                                "_DeferredAllocPagetables: ERROR call to RA_Alloc failed"));
+                                       return IMG_FALSE;
+                               }
+
+                               sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+                               ppsPTInfoList[i]->PTPageCpuVAddr =
+                                   OSMapPhysToLin(sCpuPAddr, SGX_MMU_PAGE_SIZE,
+                                                  PVRSRV_HAP_WRITECOMBINE |
+                                                  PVRSRV_HAP_KERNEL_ONLY,
+                                                  &ppsPTInfoList[i]->
+                                                  hPTPageOSMemHandle);
+                               if (!ppsPTInfoList[i]->PTPageCpuVAddr) {
+                                       PVR_DPF((PVR_DBG_ERROR,
+                                                "_DeferredAllocPagetables: ERROR failed to map page tables"));
+                                       return IMG_FALSE;
+                               }
+
+                               sDevPAddr =
+                                   SysCpuPAddrToDevPAddr
+                                   (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+#if PAGE_TEST
+                               PageTest(ppsPTInfoList[i]->PTPageCpuVAddr,
+                                        sDevPAddr);
+#endif
+                       }
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+                       pui32Tmp =
+                           (IMG_UINT32 *) ppsPTInfoList[i]->PTPageCpuVAddr;
+
+                       for (j = 0; j < SGX_MMU_PT_SIZE; j++) {
+                               pui32Tmp[j] =
+                                   pMMUHeap->psMMUContext->psDevInfo->
+                                   sDummyDataDevPAddr.
+                                   uiAddr | SGX_MMU_PTE_VALID;
+                       }
+#else
+
+                       OSMemSet(ppsPTInfoList[i]->PTPageCpuVAddr, 0,
+                                SGX_MMU_PAGE_SIZE);
+#endif
+
+                       PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX,
+                                            ppsPTInfoList[i]->PTPageCpuVAddr,
+                                            SGX_MMU_PAGE_SIZE,
+                                            PDUMP_PT_UNIQUETAG);
+
+                       PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+                                 ppsPTInfoList[i]->PTPageCpuVAddr,
+                                 SGX_MMU_PAGE_SIZE, 0, IMG_TRUE,
+                                 PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+                       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_VALID;
+
+                                               PDUMPMEM2
+                                                   (PVRSRV_DEVICE_TYPE_SGX,
+                                                    (IMG_VOID *) &
+                                                    pui32PDEntry[i],
+                                                    sizeof(IMG_UINT32), 0,
+                                                    IMG_FALSE,
+                                                    PDUMP_PD_UNIQUETAG,
+                                                    PDUMP_PT_UNIQUETAG);
+
+                                               psMMUContext =
+                                                   psMMUContext->psNext;
+                                       }
+                                       break;
+                               }
+                       case DEVICE_MEMORY_HEAP_PERCONTEXT:
+                       case DEVICE_MEMORY_HEAP_KERNEL:
+                               {
+
+                                       pui32PDEntry[i] =
+                                           sDevPAddr.
+                                           uiAddr | SGX_MMU_PDE_VALID;
+
+                                       PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+                                                 (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);
+               }
+       }
+
+       return IMG_TRUE;
+}
+
+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;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "MMU_Initialise"));
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "MMU_Initialise: ERROR call to SysAcquireData failed"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                  sizeof(MMU_CONTEXT), (IMG_VOID **) & psMMUContext, IMG_NULL);
+       if (psMMUContext == IMG_NULL) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "MMU_Initialise: ERROR call to OSAllocMem failed"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+       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, &pvPDCpuVAddr,
+                    &hPDOSMemHandle) != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "MMU_Initialise: ERROR call to OSAllocPages failed"));
+                       return PVRSRV_ERROR_GENERIC;
+               }
+
+               if (pvPDCpuVAddr) {
+                       sCpuPAddr = OSMapLinToCPUPhys(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,
+                            &psDevInfo->pvDummyPTPageCpuVAddr,
+                            &psDevInfo->hDummyPTPageOSMemHandle) !=
+                           PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "MMU_Initialise: ERROR call to OSAllocPages failed"));
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+
+                       if (psDevInfo->pvDummyPTPageCpuVAddr) {
+                               sCpuPAddr =
+                                   OSMapLinToCPUPhys(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,
+                            &psDevInfo->pvDummyDataPageCpuVAddr,
+                            &psDevInfo->hDummyDataPageOSMemHandle) !=
+                           PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "MMU_Initialise: ERROR call to OSAllocPages failed"));
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+
+                       if (psDevInfo->pvDummyDataPageCpuVAddr) {
+                               sCpuPAddr =
+                                   OSMapLinToCPUPhys(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_GENERIC;
+               }
+
+               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_GENERIC;
+               }
+#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_GENERIC;
+                       }
+
+                       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_GENERIC;
+                       }
+
+                       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_GENERIC;
+                       }
+
+                       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_GENERIC;
+                       }
+               }
+#endif
+       }
+
+       PDUMPCOMMENT("Alloc page directory");
+#ifdef SUPPORT_SGX_MMU_BYPASS
+       EnableHostAccess(psMMUContext);
+#endif
+
+       PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pvPDCpuVAddr,
+                            SGX_MMU_PAGE_SIZE, PDUMP_PD_UNIQUETAG);
+
+       if (pvPDCpuVAddr) {
+               pui32Tmp = (IMG_UINT32 *) pvPDCpuVAddr;
+       } else {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "MMU_Initialise: pvPDCpuVAddr invalid"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+       for (i = 0; i < SGX_MMU_PD_SIZE; i++) {
+               pui32Tmp[i] =
+                   psDevInfo->sDummyPTDevPAddr.uiAddr | 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_VALID;
+               }
+
+               PDUMPCOMMENT("Dummy Page table contents");
+               PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+                         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");
+               PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+                         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
+
+       PDUMPCOMMENT("Page directory contents");
+       PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0,
+                 IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+       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
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "MMU_Finalise: ERROR call to SysAcquireData failed"));
+               return;
+       }
+
+       PDUMPCOMMENT("Free page directory");
+       PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->pvPDCpuVAddr,
+                          SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+       PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX,
+                          psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE,
+                          PDUMP_PT_UNIQUETAG);
+       PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX,
+                          psDevInfo->pvDummyDataPageCpuVAddr,
+                          SGX_MMU_PAGE_SIZE, 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->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->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->
+                                             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 >> (SGX_MMU_PAGE_SHIFT +
+                                                          SGX_MMU_PT_SHIFT);
+       pui32KernelPDCpuVAddr +=
+           psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+                                                          SGX_MMU_PT_SHIFT);
+
+       PDUMPCOMMENT("Page directory shared heap range copy");
+#ifdef SUPPORT_SGX_MMU_BYPASS
+       EnableHostAccess(psMMUContext);
+#endif
+
+       for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PTPageCount;
+            ui32PDEntry++) {
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+               PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
+#endif
+
+               pui32PDCpuVAddr[ui32PDEntry] =
+                   pui32KernelPDCpuVAddr[ui32PDEntry];
+               if (pui32PDCpuVAddr[ui32PDEntry]) {
+                       PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+                                 (IMG_VOID *) & pui32PDCpuVAddr[ui32PDEntry],
+                                 sizeof(IMG_UINT32), 0, IMG_FALSE,
+                                 PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+#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_UINT32 uPageSize = HOST_PAGESIZE();
+       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 >> (SGX_MMU_PAGE_SHIFT +
+                                           SGX_MMU_PT_SHIFT);
+
+               ppsPTInfoList =
+                   &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+               {
+
+                       ui32PTIndex =
+                           (sTmpDevVAddr.
+                            uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+                       if (!ppsPTInfoList[0]) {
+                               PVR_DPF((PVR_DBG_MESSAGE,
+                                        "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08lX (VaddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",
+                                        sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,
+                                        i, ui32PDIndex, ui32PTIndex));
+
+                               sTmpDevVAddr.uiAddr += uPageSize;
+
+                               continue;
+                       }
+
+                       pui32Tmp =
+                           (IMG_UINT32 *) ppsPTInfoList[0]->PTPageCpuVAddr;
+
+                       if (!pui32Tmp) {
+                               continue;
+                       }
+
+                       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%08lX (VAddrIni:0x%08lX 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_VALID;
+#else
+
+                       pui32Tmp[ui32PTIndex] = 0;
+#endif
+               }
+
+               if (ppsPTInfoList[0]
+                   && ppsPTInfoList[0]->ui32ValidPTECount == 0) {
+                       _DeferredFreePageTable(psMMUHeap,
+                                              ui32PDIndex -
+                                              (psMMUHeap->
+                                               ui32PTBaseIndex >>
+                                               SGX_MMU_PT_SHIFT));
+                       bInvalidateDirectoryCache = IMG_TRUE;
+               }
+
+               sTmpDevVAddr.uiAddr += uPageSize;
+       }
+
+       if (bInvalidateDirectoryCache) {
+               MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->
+                                            psDevInfo);
+       } else {
+               MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->
+                                            psDevInfo);
+       }
+
+#if defined(PDUMP)
+       MMU_PDumpPageTables(psMMUHeap, sDevVAddr, uPageSize * ui32PageCount,
+                           IMG_TRUE, hUniqueTag);
+#endif
+}
+
+IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
+                           IMG_UINT32 ui32Start,
+                           IMG_UINT32 ui32End, IMG_HANDLE hUniqueTag)
+{
+       MMU_HEAP *pMMUHeap = (MMU_HEAP *) pvMMUHeap;
+       IMG_DEV_VIRTADDR Start;
+
+       Start.uiAddr = ui32Start;
+
+       MMU_UnmapPagesAndFreePTs(pMMUHeap, Start,
+                                (ui32End - ui32Start) / SGX_MMU_PAGE_SIZE,
+                                hUniqueTag);
+}
+
+MMU_HEAP *MMU_Create(MMU_CONTEXT * psMMUContext,
+                    DEV_ARENA_DESCRIPTOR * psDevArena, RA_ARENA ** ppsVMArena)
+{
+       MMU_HEAP *pMMUHeap;
+       IMG_BOOL bRes;
+
+       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);
+       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;
+
+       bRes = _AllocPageTables(pMMUHeap);
+       if (!bRes) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "MMU_Create: ERROR call to _AllocPageTables failed"));
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL);
+               return IMG_NULL;
+       }
+
+       pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
+                                       psDevArena->BaseDevVAddr.uiAddr,
+                                       psDevArena->ui32Size,
+                                       IMG_NULL,
+                                       SGX_MMU_PAGE_SIZE,
+                                       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"));
+               _DeferredFreePageTables(pMMUHeap);
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL);
+               return IMG_NULL;
+       }
+#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(EUR_CR_BIF_TILE0, ui32RegVal);
+       }
+#endif
+
+       *ppsVMArena = pMMUHeap->psVMArena;
+
+       return pMMUHeap;
+}
+
+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);
+               }
+#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, 0, 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) {
+               bStatus = RA_Alloc(pMMUHeap->psVMArena,
+                                  uSize,
+                                  pActualSize,
+                                  IMG_NULL,
+                                  0,
+                                  uDevVAddrAlignment,
+                                  0, &(psDevVAddr->uiAddr));
+               if (!bStatus) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "MMU_Alloc: RA_Alloc of VMArena failed"));
+                       return bStatus;
+               }
+       }
+#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"));
+               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: mmu=%08X, dev_vaddr=%08X", pMMUHeap,
+                DevVAddr.uiAddr));
+
+       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 find DevVAddr %08X in a DevArena",
+                DevVAddr.uiAddr));
+}
+
+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 + SGX_MMU_PAGE_SIZE - 1) >> SGX_MMU_PAGE_SHIFT;
+
+       ui32PDIndex =
+           DevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+       ui32PTIndex = (DevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+       PDUMPCOMMENT("Page table mods (num entries == %08X) %s",
+                    ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
+
+       while (ui32NumPTEntries > 0) {
+               MMU_PT_INFO *psPTInfo = *ppsPTInfoList++;
+
+               if (ui32NumPTEntries <= 1024 - ui32PTIndex) {
+                       ui32PTDumpCount = ui32NumPTEntries;
+               } else {
+                       ui32PTDumpCount = 1024 - ui32PTIndex;
+               }
+
+               if (psPTInfo) {
+                       pui32PTEntry = (IMG_UINT32 *) psPTInfo->PTPageCpuVAddr;
+                       PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+                                 (IMG_VOID *) & pui32PTEntry[ui32PTIndex],
+                                 ui32PTDumpCount * sizeof(IMG_UINT32), 0,
+                                 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;
+
+       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 >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+       ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+
+       ui32Index = (DevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+       pui32Tmp = (IMG_UINT32 *) ppsPTInfoList[0]->PTPageCpuVAddr;
+
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+       if (pui32Tmp[ui32Index] & SGX_MMU_PTE_VALID) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "MMU_MapPage: Page is already valid for alloc at VAddr:0x%08lX PDIdx:%u PTIdx:%u",
+                        DevVAddr.uiAddr,
+                        DevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+                                            SGX_MMU_PT_SHIFT), ui32Index));
+       }
+
+       PVR_ASSERT((pui32Tmp[ui32Index] & SGX_MMU_PTE_VALID) == 0);
+#endif
+
+       ppsPTInfoList[0]->ui32ValidPTECount++;
+
+       pui32Tmp[ui32Index] = (DevPAddr.uiAddr & SGX_MMU_PTE_ADDR_MASK)
+           | SGX_MMU_PTE_VALID | ui32MMUFlags;
+}
+
+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 += SGX_MMU_PAGE_SIZE) {
+               IMG_SYS_PHYADDR sSysAddr;
+
+               sSysAddr = psSysAddr[i];
+
+               DevPAddr =
+                   SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
+
+               MMU_MapPage(pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+               DevVAddr.uiAddr += SGX_MMU_PAGE_SIZE;
+
+               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 = SGX_MMU_PAGE_SIZE;
+       IMG_UINT32 ui32PAdvance = SGX_MMU_PAGE_SIZE;
+
+       PVR_ASSERT(pMMUHeap != IMG_NULL);
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "MMU_MapPages: mmu=%08X, devVAddr=%08X, SysPAddr=%08X, size=0x%x",
+                pMMUHeap, DevVAddr.uiAddr, SysPAddr.uiAddr, uSize));
+
+#if defined(PDUMP)
+       MapBaseDevVAddr = DevVAddr;
+#else
+       PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+       DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+#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 = SGX_MMU_PAGE_SIZE;
+       IMG_UINT32 ui32PAdvance = SGX_MMU_PAGE_SIZE;
+
+#if !defined (PDUMP)
+       PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "MMU_MapShadow: %08X, 0x%x, %08X",
+                MapBaseDevVAddr.uiAddr, uByteSize, CpuVAddr));
+
+       PVR_ASSERT(((IMG_UINT32) CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+       PVR_ASSERT(((IMG_UINT32) uByteSize & (SGX_MMU_PAGE_SIZE - 1)) == 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((IMG_VOID *) ((IMG_UINT32)
+                                                           CpuVAddr +
+                                                           uOffset));
+               } else {
+                       CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+               }
+               DevPAddr =
+                   SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+               PVR_DPF((PVR_DBG_MESSAGE,
+                        "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 = HOST_PAGESIZE();
+       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 >> (SGX_MMU_PAGE_SHIFT +
+                                           SGX_MMU_PT_SHIFT);
+
+               ppsPTInfoList =
+                   &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+               ui32PTIndex =
+                   (sTmpDevVAddr.
+                    uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+               if (!ppsPTInfoList[0]) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08lX (VaddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",
+                                sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr, i,
+                                ui32PDIndex, ui32PTIndex));
+
+                       sTmpDevVAddr.uiAddr += uPageSize;
+
+                       continue;
+               }
+
+               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%08lX (VAddrIni:0x%08lX 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_VALID;
+#else
+
+               pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+               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 >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+       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 & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+       pui32PageTable = (IMG_UINT32 *) ppsPTInfoList[0]->PTPageCpuVAddr;
+
+       sDevPAddr.uiAddr = pui32PageTable[ui32Index];
+
+       sDevPAddr.uiAddr &= SGX_MMU_PTE_ADDR_MASK;
+
+       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;
+       }
+
+       PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+       *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;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "MMU_BIFResetPDAlloc: ERROR call to SysAcquireData failed"));
+               return eError;
+       }
+
+       psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+       if (psLocalDevMemArena == IMG_NULL) {
+
+               eError =
+                   OSAllocPages(PVRSRV_HAP_WRITECOMBINE |
+                                PVRSRV_HAP_KERNEL_ONLY, 3 * 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(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)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       RA_ARENA *psLocalDevMemArena;
+       IMG_SYS_PHYADDR sPDSysPAddr;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "MMU_BIFResetPDFree: ERROR call to SysAcquireData failed"));
+               return;
+       }
+
+       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 PAGE_TEST
+static void PageTest(void *pMem, IMG_DEV_PHYADDR sDevPAddr)
+{
+       volatile IMG_UINT32 ui32WriteData;
+       volatile IMG_UINT32 ui32ReadData;
+       volatile IMG_UINT32 *pMem32 = (volatile IMG_UINT32 *)pMem;
+       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/pvr/mmu.h b/pvr/mmu.h
new file mode 100644 (file)
index 0000000..1a4e0f8
--- /dev/null
+++ b/pvr/mmu.h
@@ -0,0 +1,103 @@
+/**********************************************************************
+ *
+ * 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);
+
+IMG_VOID MMU_Delete(MMU_HEAP * pMMU);
+
+IMG_BOOL
+MMU_Alloc(MMU_HEAP * pMMU,
+         IMG_SIZE_T uSize,
+         IMG_SIZE_T * pActualSize,
+         IMG_UINT32 uFlags,
+         IMG_UINT32 uDevVAddrAlignment, IMG_DEV_VIRTADDR * pDevVAddr);
+
+IMG_VOID
+MMU_Free(MMU_HEAP * pMMU, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size);
+
+IMG_VOID MMU_Enable(MMU_HEAP * pMMU);
+
+IMG_VOID MMU_Disable(MMU_HEAP * pMMU);
+
+IMG_VOID
+MMU_MapPages(MMU_HEAP * pMMU,
+            IMG_DEV_VIRTADDR devVAddr,
+            IMG_SYS_PHYADDR SysPAddr,
+            IMG_SIZE_T uSize, IMG_UINT32 ui32MemFlags, IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapShadow(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
+MMU_UnmapPages(MMU_HEAP * pMMU,
+              IMG_DEV_VIRTADDR dev_vaddr,
+              IMG_UINT32 ui32PageCount, IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapScatter(MMU_HEAP * pMMU,
+              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);
+
+#endif
diff --git a/pvr/module.c b/pvr/module.c
new file mode 100644 (file)
index 0000000..2084705
--- /dev/null
@@ -0,0 +1,522 @@
+/**********************************************************************
+ *
+ * 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 AUTOCONF_INCLUDED
+#include <linux/config.h>
+#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(LDM_PLATFORM)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(LDM_PCI)
+#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 "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"
+
+#define DRVNAME                "pvrsrvkm"
+#define DEVNAME                "pvrsrvkm"
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+#ifdef DEBUG
+static int debug = DBGPRIV_WARNING;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+#include <linux/moduleparam.h>
+module_param(debug, int, 0);
+#else
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Sets the level of debug output (default=0x4)");
+#endif
+#endif
+
+void PVRDebugSetLevel(IMG_UINT32 uDebugLevel);
+
+extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *
+                                        psJTable);
+extern IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *
+                                       psJTable);
+EXPORT_SYMBOL(PVRGetDisplayClassJTable);
+EXPORT_SYMBOL(PVRGetBufferClassJTable);
+
+static int AssignedMajorNumber;
+
+extern int PVRSRV_BridgeDispatchKM(struct inode *inode, struct file *file,
+                                  unsigned int cmd, unsigned long arg);
+static int PVRSRVOpen(struct inode *pInode, struct file *pFile);
+static int PVRSRVRelease(struct inode *pInode, struct file *pFile);
+
+PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+static struct file_operations pvrsrv_fops = {
+owner: THIS_MODULE,
+ioctl: PVRSRV_BridgeDispatchKM,
+open:  PVRSRVOpen,
+release:PVRSRVRelease,
+mmap:  PVRMMap,
+};
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+static IMG_UINT32 gPVRPowerLevel;
+#endif
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
+#if defined(LDM_PLATFORM)
+#define        LDM_DEV struct platform_device
+#define        LDM_DRV struct platform_driver
+#if defined(LDM_PCI)
+#undef LDM_PCI
+#endif
+#endif
+
+#if defined(LDM_PCI)
+#define        LDM_DEV struct pci_dev
+#define        LDM_DRV struct pci_driver
+#endif
+
+#if defined(LDM_PLATFORM)
+static int PVRSRVDriverRemove(LDM_DEV * device);
+static int PVRSRVDriverProbe(LDM_DEV * device);
+#endif
+#if defined(LDM_PCI)
+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(LDM_PCI)
+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(LDM_PLATFORM)
+       .driver = {
+                  .name = DRVNAME,
+                  },
+#endif
+#if defined(LDM_PCI)
+       .name = DRVNAME,
+       .id_table = powervr_id_table,
+#endif
+       .probe = PVRSRVDriverProbe,
+#if defined(LDM_PLATFORM)
+       .remove = PVRSRVDriverRemove,
+#endif
+#if defined(LDM_PCI)
+       .remove = __devexit_p(PVRSRVDriverRemove),
+#endif
+       .suspend = PVRSRVDriverSuspend,
+       .resume = PVRSRVDriverResume,
+       .shutdown = PVRSRVDriverShutdown,
+};
+
+LDM_DEV *gpsPVRLDMDev;
+
+#if defined(LDM_PLATFORM)
+static void PVRSRVDeviceRelease(struct device *device);
+
+static struct platform_device powervr_device = {
+       .name = DEVNAME,
+       .id = -1,
+       .dev = {
+               .release = PVRSRVDeviceRelease}
+};
+#endif
+
+#if defined(LDM_PLATFORM)
+static int PVRSRVDriverProbe(LDM_DEV * pDevice)
+#endif
+#if defined(LDM_PCI)
+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
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               gpsPVRLDMDev = pDevice;
+
+               if (SysInitialise() != PVRSRV_OK) {
+                       return -ENODEV;
+               }
+       }
+
+       return 0;
+}
+
+#if defined (LDM_PLATFORM)
+static int PVRSRVDriverRemove(LDM_DEV * pDevice)
+#endif
+#if defined(LDM_PCI)
+static 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_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 (LDM_PLATFORM)
+       return 0;
+#endif
+#if defined (LDM_PCI)
+       return;
+#endif
+}
+
+static void PVRSRVDriverShutdown(LDM_DEV * pDevice)
+{
+       PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+       (void)PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D3);
+}
+
+static int PVRSRVDriverSuspend(LDM_DEV * pDevice, pm_message_t state)
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL))
+       PVR_TRACE(("PVRSRVDriverSuspend(pDevice=%p)", pDevice));
+
+       if (PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D3) != PVRSRV_OK) {
+               return -EINVAL;
+       }
+#endif
+       return 0;
+}
+
+static int PVRSRVDriverResume(LDM_DEV * pDevice)
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL))
+       PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
+
+       if (PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D0) != PVRSRV_OK) {
+               return -EINVAL;
+       }
+#endif
+       return 0;
+}
+
+#if defined(LDM_PLATFORM)
+static void PVRSRVDeviceRelease(struct device *pDevice)
+{
+       PVR_DPF((PVR_DBG_WARNING, "PVRSRVDeviceRelease(pDevice=%p)", pDevice));
+}
+#endif
+#endif
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+int PVRProcSetPowerLevel(struct file *file, const char *buffer,
+                        unsigned long count, void *data)
+{
+       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_POWER_STATE_D3)
+                                   != PVRSRV_OK) {
+                                       return -EINVAL;
+                               }
+                       } else {
+                               if (PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D0)
+                                   != PVRSRV_OK) {
+                                       return -EINVAL;
+                               }
+                       }
+
+                       gPVRPowerLevel = PVRPowerLevel;
+               }
+       }
+       return (count);
+}
+
+int PVRProcGetPowerLevel(char *page, char **start, off_t off, int count,
+                        int *eof, void *data)
+{
+       if (off == 0) {
+               *start = (char *)1;
+               return printAppend(page, count, 0, "%lu\n", gPVRPowerLevel);
+       }
+       *eof = 1;
+       return 0;
+}
+#endif
+
+static int PVRSRVOpen(struct inode unref__ * pInode,
+                     struct file unref__ * pFile)
+{
+       int Ret = 0;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       if (PVRSRVProcessConnect(OSGetCurrentProcessIDKM()) != PVRSRV_OK) {
+               Ret = -ENOMEM;
+       }
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+
+       return Ret;
+}
+
+static int PVRSRVRelease(struct inode unref__ * pInode,
+                        struct file unref__ * pFile)
+{
+       int Ret = 0;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       PVRSRVProcessDisconnect(OSGetCurrentProcessIDKM());
+
+       LinuxUnLockMutex(&gPVRSRVLock);
+
+       return Ret;
+}
+
+static int __init PVRCore_Init(void)
+{
+       int error;
+#if !(defined(LDM_PLATFORM) || defined(LDM_PCI))
+       PVRSRV_ERROR eError;
+#endif
+
+       PVR_TRACE(("PVRCore_Init"));
+
+       AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
+
+       if (AssignedMajorNumber <= 0) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRCore_Init: unable to get major number"));
+
+               return -EBUSY;
+       }
+
+       PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
+
+       if (CreateProcEntries()) {
+               unregister_chrdev(AssignedMajorNumber, DRVNAME);
+
+               return -ENOMEM;
+       }
+
+       LinuxInitMutex(&gPVRSRVLock);
+
+#ifdef DEBUG
+       PVRDebugSetLevel(debug);
+#endif
+
+       if (LinuxMMInit() != PVRSRV_OK) {
+               error = -ENOMEM;
+               goto init_failed;
+       }
+
+       LinuxBridgeInit();
+
+       PVRMMapInit();
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
+#if defined(LDM_PLATFORM)
+       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 ((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
+
+#if defined(LDM_PCI)
+       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
+
+       return 0;
+
+init_failed:
+
+       PVRMMapCleanup();
+       LinuxMMCleanup();
+       RemoveProcEntries();
+       unregister_chrdev(AssignedMajorNumber, DRVNAME);
+
+       return error;
+
+}
+
+static void __exit PVRCore_Cleanup(void)
+{
+       SYS_DATA *psSysData;
+
+       PVR_TRACE(("PVRCore_Cleanup"));
+
+       SysAcquireData(&psSysData);
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+       if (
+#endif
+                  unregister_chrdev(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
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
+#if defined(LDM_PCI)
+       pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (LDM_PLATFORM)
+       platform_device_unregister(&powervr_device);
+       platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+       if (gPVRPowerLevel != 0) {
+               if (PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D0) == PVRSRV_OK) {
+                       gPVRPowerLevel = 0;
+               }
+       }
+#endif
+
+       SysDeinitialise(psSysData);
+#endif
+
+       PVRMMapCleanup();
+
+       LinuxMMCleanup();
+
+       LinuxBridgeDeInit();
+
+       RemoveProcEntries();
+
+       PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
diff --git a/pvr/modules.order b/pvr/modules.order
new file mode 100644 (file)
index 0000000..33eed37
--- /dev/null
@@ -0,0 +1,2 @@
+kernel//home/pratheesh/webkit/release_work/omap3-sgx-modules-1.3.13.1607/services4/3rdparty/dc_omap3430_linux/omaplfb.ko
+kernel//home/pratheesh/webkit/release_work/omap3-sgx-modules-1.3.13.1607/pvrsrvkm.ko
diff --git a/pvr/mutex.c b/pvr/mutex.c
new file mode 100644 (file)
index 0000000..6381282
--- /dev/null
@@ -0,0 +1,127 @@
+/**********************************************************************
+ *
+ * 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 LinuxInitMutex(PVRSRV_LINUX_MUTEX * psPVRSRVMutex)
+{
+       mutex_init(psPVRSRVMutex);
+}
+
+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_GENERIC;
+       } 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);
+}
+
+#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_GENERIC;
+       } 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/pvr/mutex.h b/pvr/mutex.h
new file mode 100644 (file)
index 0000000..41223f6
--- /dev/null
@@ -0,0 +1,65 @@
+/**********************************************************************
+ *
+ * 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
+
+extern IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX * psPVRSRVMutex);
+
+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/pvr/oemfuncs.h b/pvr/oemfuncs.h
new file mode 100644 (file)
index 0000000..9225b0d
--- /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(__OEMFUNCS_H__)
+#define __OEMFUNCS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+       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 struct PVRSRV_DC_OEM_JTABLE_TAG {
+               PFN_SRV_BRIDGEDISPATCH pfnOEMBridgeDispatch;
+               IMG_PVOID pvDummy1;
+               IMG_PVOID pvDummy2;
+               IMG_PVOID pvDummy3;
+
+       } PVRSRV_DC_OEM_JTABLE;
+
+#define OEM_GET_EXT_FUNCS                      (1<<1)
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/omaplfb.h b/pvr/omaplfb.h
new file mode 100644 (file)
index 0000000..d10cdd7
--- /dev/null
@@ -0,0 +1,208 @@
+/**********************************************************************
+ *
+ * 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 __OMAPLFB_H__
+#define __OMAPLFB_H__
+
+extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *
+                                        psJTable);
+
+#define OMAPLCD_IRQ                    25
+
+#define OMAPLCD_SYSCONFIG              0x0410
+#define OMAPLCD_CONFIG                 0x0444
+#define OMAPLCD_DEFAULT_COLOR0         0x044C
+#define OMAPLCD_TIMING_H               0x0464
+#define OMAPLCD_TIMING_V               0x0468
+#define OMAPLCD_POL_FREQ               0x046C
+#define OMAPLCD_DIVISOR                        0x0470
+#define OMAPLCD_SIZE_DIG               0x0478
+#define OMAPLCD_SIZE_LCD               0x047C
+#define OMAPLCD_GFX_POSITION           0x0488
+#define OMAPLCD_GFX_SIZE               0x048C
+#define OMAPLCD_GFX_ATTRIBUTES         0x04a0
+#define OMAPLCD_GFX_FIFO_THRESHOLD     0x04a4
+#define OMAPLCD_GFX_WINDOW_SKIP                0x04b4
+
+#define OMAPLCD_IRQSTATUS              0x0418
+#define OMAPLCD_IRQENABLE              0x041c
+#define OMAPLCD_CONTROL                        0x0440
+#define OMAPLCD_GFX_BA0                        0x0480
+#define OMAPLCD_GFX_BA1                        0x0484
+#define OMAPLCD_GFX_ROW_INC            0x04ac
+#define OMAPLCD_GFX_PIX_INC            0x04b0
+#define OMAPLCD_VID1_BA0               0x04bc
+#define OMAPLCD_VID1_BA1               0x04c0
+#define OMAPLCD_VID1_ROW_INC           0x04d8
+#define OMAPLCD_VID1_PIX_INC           0x04dc
+
+#define        OMAP_CONTROL_GODIGITAL          (1 << 6)
+#define        OMAP_CONTROL_GOLCD              (1 << 5)
+#define        OMAP_CONTROL_DIGITALENABLE      (1 << 1)
+#define        OMAP_CONTROL_LCDENABLE          (1 << 0)
+
+#define OMAPLCD_INTMASK_VSYNC          (1 << 1)
+#define OMAPLCD_INTMASK_OFF            0
+
+typedef struct OMAPLFB_BUFFER_TAG {
+       IMG_SYS_PHYADDR sSysAddr;
+       IMG_CPU_VIRTADDR sCPUVAddr;
+       IMG_UINT32 ui32BufferSize;
+       PVRSRV_SYNC_DATA *psSyncData;
+       struct OMAPLFB_BUFFER_TAG *psNext;
+} OMAPLFB_BUFFER;
+
+typedef struct OMAPLFB_VSYNC_FLIP_ITEM_TAG {
+
+       IMG_HANDLE hCmdComplete;
+
+       IMG_SYS_PHYADDR *sSysAddr;
+
+       IMG_UINT32 ui32SwapInterval;
+
+       IMG_BOOL bValid;
+
+       IMG_BOOL bFlipped;
+
+       IMG_BOOL bCmdCompleted;
+
+} OMAPLFB_VSYNC_FLIP_ITEM;
+
+typedef struct PVRPDP_SWAPCHAIN_TAG {
+
+       IMG_UINT32 ui32BufferCount;
+
+       OMAPLFB_BUFFER *psBuffer;
+
+       OMAPLFB_VSYNC_FLIP_ITEM *psVSyncFlips;
+
+       IMG_UINT32 ui32InsertIndex;
+
+       IMG_UINT32 ui32RemoveIndex;
+
+       IMG_VOID *pvRegs;
+
+       PVRSRV_DC_DISP2SRV_KMJTABLE *psPVRJTable;
+
+       IMG_BOOL bFlushCommands;
+
+       IMG_UINT32 ui32SetFlushStateRefCount;
+
+       IMG_BOOL bBlanked;
+
+       spinlock_t *psSwapChainLock;
+} OMAPLFB_SWAPCHAIN;
+
+typedef struct OMAPLFB_FBINFO_TAG {
+       IMG_SYS_PHYADDR sSysAddr;
+       IMG_CPU_VIRTADDR sCPUVAddr;
+       IMG_UINT32 ui32FBSize;
+       IMG_UINT32 ui32BufferSize;
+       IMG_UINT32 ui32RoundedBufferSize;
+       IMG_UINT32 ui32Width;
+       IMG_UINT32 ui32Height;
+       IMG_UINT32 ui32ByteStride;
+
+       PVRSRV_PIXEL_FORMAT ePixelFormat;
+} OMAPLFB_FBINFO;
+
+typedef struct OMAPLFB_DEVINFO_TAG {
+       IMG_UINT32 ui32DeviceID;
+       DISPLAY_INFO sDisplayInfo;
+
+       OMAPLFB_BUFFER sSystemBuffer;
+
+       DISPLAY_FORMAT sDisplayFormat;
+
+       DISPLAY_DIMS sDisplayDim;
+
+       PVRSRV_DC_DISP2SRV_KMJTABLE sPVRJTable;
+
+       PVRSRV_DC_SRV2DISP_KMJTABLE sDCJTable;
+
+       OMAPLFB_FBINFO sFBInfo;
+
+       IMG_UINT32 ui32RefCount;
+
+       OMAPLFB_SWAPCHAIN *psSwapChain;
+
+       IMG_BOOL bFlushCommands;
+
+       IMG_DEV_VIRTADDR sDisplayDevVAddr;
+
+       struct fb_info *psLINFBInfo;
+
+       struct notifier_block sLINNotifBlock;
+
+       IMG_BOOL bDeviceSuspended;
+
+       spinlock_t *psSwapChainLock;
+} OMAPLFB_DEVINFO;
+
+#define        OMAPLFB_PAGE_SIZE 4096
+#define        OMAPLFB_PAGE_MASK (OMAPLFB_PAGE_SIZE - 1)
+#define        OMAPLFB_PAGE_TRUNC (~OMAPLFB_PAGE_MASK)
+
+#define        OMAPLFB_PAGE_ROUNDUP(x) (((x) + OMAPLFB_PAGE_MASK) & OMAPLFB_PAGE_TRUNC)
+
+#ifdef DEBUG
+#define        DEBUG_PRINTK(x) printk x
+#else
+#define        DEBUG_PRINTK(x)
+#endif
+
+#define DISPLAY_DEVICE_NAME "PowerVR OMAP Linux Display Driver"
+#define        DRVNAME "omaplfb"
+#define        DEVNAME DRVNAME
+#define        DRIVER_PREFIX DRVNAME
+
+PVRSRV_ERROR OMAPLFBInit(IMG_VOID);
+PVRSRV_ERROR OMAPLFBDeinit(IMG_VOID);
+
+#ifdef LDM_PLATFORM
+IMG_VOID OMAPLFBDriverSuspend(IMG_VOID);
+IMG_VOID OMAPLFBDriverResume(IMG_VOID);
+#endif
+
+IMG_VOID *OMAPLFBAllocKernelMem(IMG_UINT32 ui32Size);
+IMG_VOID OMAPLFBFreeKernelMem(IMG_VOID * pvMem);
+PVRSRV_ERROR OMAPLFBGetLibFuncAddr(IMG_CHAR * szFunctionName,
+                                  PFN_DC_GET_PVRJTABLE * ppfnFuncTable);
+PVRSRV_ERROR OMAPLFBInstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain);
+PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain);
+IMG_BOOL OMAPLFBVSyncIHandler(OMAPLFB_SWAPCHAIN * psSwapChain);
+IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain);
+IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain);
+#if defined (SUPPORT_TI_DSS_FW)
+IMG_VOID OMAPLFBEnableDisplayRegisterAccess(IMG_VOID);
+IMG_VOID OMAPLFBDisableDisplayRegisterAccess(IMG_VOID);
+#endif
+#if defined (CONFIG_OMAP2_DSS)
+IMG_VOID OMAPLFBFlipDSS2(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr);
+#endif
+IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr);
+
+#endif
diff --git a/pvr/omaplfb_displayclass.c b/pvr/omaplfb_displayclass.c
new file mode 100644 (file)
index 0000000..55e6f81
--- /dev/null
@@ -0,0 +1,1356 @@
+/**********************************************************************
+ *
+ * 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 "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "omaplfb.h"
+
+static IMG_VOID *gpvAnchor;
+
+static int fb_idx = 0;
+
+#define OMAPLFB_COMMAND_COUNT          1
+
+static PFN_DC_GET_PVRJTABLE pfnGetPVRJTable = IMG_NULL;
+
+static OMAPLFB_DEVINFO *GetAnchorPtr(IMG_VOID)
+{
+       return (OMAPLFB_DEVINFO *) gpvAnchor;
+}
+
+static IMG_VOID SetAnchorPtr(OMAPLFB_DEVINFO * psDevInfo)
+{
+       gpvAnchor = (IMG_VOID *) psDevInfo;
+}
+
+static IMG_VOID FlushInternalVSyncQueue(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+       OMAPLFB_VSYNC_FLIP_ITEM *psFlipItem;
+       IMG_UINT32 ui32MaxIndex;
+       IMG_UINT32 i;
+
+       psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ui32RemoveIndex];
+       ui32MaxIndex = psSwapChain->ui32BufferCount - 1;
+
+       for (i = 0; i < psSwapChain->ui32BufferCount; i++) {
+               if (!psFlipItem->bValid) {
+                       continue;
+               }
+
+               DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                             ": FlushInternalVSyncQueue: Flushing swap buffer (index %lu)\n",
+                             psSwapChain->ui32RemoveIndex));
+
+               if (psFlipItem->bFlipped == IMG_FALSE) {
+
+                       OMAPLFBFlip(psSwapChain,
+                                   (IMG_UINT32) psFlipItem->sSysAddr);
+               }
+
+               if (psFlipItem->bCmdCompleted == IMG_FALSE) {
+                       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                                     ": FlushInternalVSyncQueue: Calling command complete for swap buffer (index %lu)\n",
+                                     psSwapChain->ui32RemoveIndex));
+
+                       psSwapChain->psPVRJTable->
+                           pfnPVRSRVCmdComplete(psFlipItem->hCmdComplete,
+                                                IMG_TRUE);
+               }
+
+               psSwapChain->ui32RemoveIndex++;
+
+               if (psSwapChain->ui32RemoveIndex > ui32MaxIndex) {
+                       psSwapChain->ui32RemoveIndex = 0;
+               }
+
+               psFlipItem->bFlipped = IMG_FALSE;
+               psFlipItem->bCmdCompleted = IMG_FALSE;
+               psFlipItem->bValid = IMG_FALSE;
+
+               psFlipItem =
+                   &psSwapChain->psVSyncFlips[psSwapChain->ui32RemoveIndex];
+       }
+
+       psSwapChain->ui32InsertIndex = 0;
+       psSwapChain->ui32RemoveIndex = 0;
+}
+
+static IMG_VOID SetFlushStateInternalNoLock(OMAPLFB_DEVINFO * psDevInfo,
+                                           IMG_BOOL bFlushState)
+{
+       OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
+
+       if (psSwapChain == IMG_NULL) {
+               return;
+       }
+
+       if (bFlushState) {
+               if (psSwapChain->ui32SetFlushStateRefCount == 0) {
+                       OMAPLFBDisableVSyncInterrupt(psSwapChain);
+                       psSwapChain->bFlushCommands = IMG_TRUE;
+                       FlushInternalVSyncQueue(psSwapChain);
+               }
+               psSwapChain->ui32SetFlushStateRefCount++;
+       } else {
+               if (psSwapChain->ui32SetFlushStateRefCount != 0) {
+                       psSwapChain->ui32SetFlushStateRefCount--;
+                       if (psSwapChain->ui32SetFlushStateRefCount == 0) {
+                               psSwapChain->bFlushCommands = IMG_FALSE;
+                               OMAPLFBEnableVSyncInterrupt(psSwapChain);
+                       }
+               }
+       }
+}
+
+static IMG_VOID SetFlushStateInternal(OMAPLFB_DEVINFO * psDevInfo,
+                                     IMG_BOOL bFlushState)
+{
+       unsigned long ulLockFlags;
+
+       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       SetFlushStateInternalNoLock(psDevInfo, bFlushState);
+
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+}
+
+static IMG_VOID SetFlushStateExternal(OMAPLFB_DEVINFO * psDevInfo,
+                                     IMG_BOOL bFlushState)
+{
+       unsigned long ulLockFlags;
+
+       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       if (psDevInfo->bFlushCommands != bFlushState) {
+               psDevInfo->bFlushCommands = bFlushState;
+               SetFlushStateInternalNoLock(psDevInfo, bFlushState);
+       }
+
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+}
+
+static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
+{
+       OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+
+       switch (ui32State) {
+       case DC_STATE_FLUSH_COMMANDS:
+               SetFlushStateExternal(psDevInfo, IMG_TRUE);
+               break;
+       case DC_STATE_NO_FLUSH_COMMANDS:
+               SetFlushStateExternal(psDevInfo, IMG_FALSE);
+               break;
+       default:
+               break;
+       }
+
+       return;
+}
+
+static int FrameBufferEvents(struct notifier_block *psNotif,
+                            unsigned long event, void *data)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+       OMAPLFB_SWAPCHAIN *psSwapChain;
+       struct fb_event *psFBEvent = (struct fb_event *)data;
+       IMG_BOOL bBlanked;;
+
+       if (event != FB_EVENT_BLANK) {
+               return 0;
+       }
+
+       psDevInfo = GetAnchorPtr();
+       psSwapChain = psDevInfo->psSwapChain;
+
+       bBlanked = (*(int *)psFBEvent->data != 0);
+
+       if (bBlanked != psSwapChain->bBlanked) {
+               psSwapChain->bBlanked = bBlanked;
+
+               if (bBlanked) {
+
+                       SetFlushStateInternal(psDevInfo, IMG_TRUE);
+               } else {
+
+                       SetFlushStateInternal(psDevInfo, IMG_FALSE);
+               }
+       }
+
+       return 0;
+}
+
+static PVRSRV_ERROR UnblankDisplay(OMAPLFB_DEVINFO * psDevInfo)
+{
+       int res;
+
+       acquire_console_sem();
+       res = fb_blank(psDevInfo->psLINFBInfo, 0);
+       release_console_sem();
+#if !defined (CONFIG_OMAP2_DSS)
+       /* DSS2 returns error if unblank from a non-suspend state
+          ignore the error status for timebeing */
+       if (res != 0) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": fb_blank failed (%d)", res);
+               return PVRSRV_ERROR_GENERIC;
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+#if defined (CONFIG_OMAP2_DSS)
+
+/*
+        Flip implementation for DSS2 using fb_pan_display
+*/
+IMG_VOID OMAPLFBFlipDSS2(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr)
+{
+       OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
+       struct fb_var_screeninfo var;
+       memcpy(&var, &psLINFBInfo->var, sizeof(struct fb_var_screeninfo));
+       var.yoffset =
+           (aPhyAddr -
+            psLINFBInfo->fix.smem_start) / psLINFBInfo->fix.line_length;
+       if (psLINFBInfo->fbops->fb_pan_display != NULL) {
+               psLINFBInfo->fbops->fb_pan_display(&var, psLINFBInfo);
+
+       }
+}
+#endif
+
+static PVRSRV_ERROR EnableLFBEventNotification(OMAPLFB_DEVINFO * psDevInfo)
+{
+       int res;
+       OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
+       PVRSRV_ERROR eError;
+
+       memset(&psDevInfo->sLINNotifBlock, 0,
+              sizeof(psDevInfo->sLINNotifBlock));
+
+       psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;
+
+       psSwapChain->bBlanked = IMG_FALSE;
+
+       res = fb_register_client(&psDevInfo->sLINNotifBlock);
+       if (res != 0) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": fb_register_client failed (%d)", res);
+
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       eError = UnblankDisplay(psDevInfo);
+       if (eError != PVRSRV_OK) {
+               DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+                             ": UnblankDisplay failed (%d)", eError));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DisableLFBEventNotification(OMAPLFB_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 PVRSRV_ERROR_GENERIC;
+       }
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 ui32DeviceID,
+                                IMG_HANDLE * phDevice,
+                                PVRSRV_SYNC_DATA * psSystemBufferSyncData)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(ui32DeviceID);
+
+       psDevInfo = GetAnchorPtr();
+
+       psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
+
+       eError = UnblankDisplay(psDevInfo);
+       if (eError != PVRSRV_OK) {
+               DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+                             ": UnblankDisplay failed (%d)", eError));
+               return eError;
+       }
+
+       *phDevice = (IMG_HANDLE) psDevInfo;
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
+{
+       PVR_UNREFERENCED_PARAMETER(hDevice);
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
+                                 IMG_UINT32 * pui32NumFormats,
+                                 DISPLAY_FORMAT * psFormat)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+
+       if (!hDevice || !pui32NumFormats) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_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)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+
+       if (!hDevice || !psFormat || !pui32NumDims) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+
+       *pui32NumDims = 1;
+
+       if (psDim) {
+               psDim[0] = psDevInfo->sDisplayDim;
+       }
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE * phBuffer)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+
+       if (!hDevice || !phBuffer) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+
+       *phBuffer = (IMG_HANDLE) & psDevInfo->sSystemBuffer;
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO * psDCInfo)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+
+       if (!hDevice || !psDCInfo) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+
+       *psDCInfo = psDevInfo->sDisplayInfo;
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE hDevice,
+                                   IMG_HANDLE hBuffer,
+                                   IMG_SYS_PHYADDR ** ppsSysAddr,
+                                   IMG_UINT32 * pui32ByteSize,
+                                   IMG_VOID ** ppvCpuVAddr,
+                                   IMG_HANDLE * phOSMapInfo,
+                                   IMG_BOOL * pbIsContiguous)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+       OMAPLFB_BUFFER *psSystemBuffer;
+
+       if (!hDevice) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+
+       if (!hBuffer) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       psSystemBuffer = (OMAPLFB_BUFFER *) hBuffer;
+
+       if (!ppsSysAddr) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       *ppsSysAddr = &psSystemBuffer->sSysAddr;
+
+       if (!pui32ByteSize) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       *pui32ByteSize = psDevInfo->sFBInfo.ui32BufferSize;
+
+       if (ppvCpuVAddr) {
+               *ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
+       }
+
+       if (phOSMapInfo) {
+               *phOSMapInfo = (IMG_HANDLE) 0;
+       }
+
+       if (pbIsContiguous) {
+               *pbIsContiguous = IMG_TRUE;
+       }
+
+       return PVRSRV_OK;
+}
+
+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)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+       OMAPLFB_SWAPCHAIN *psSwapChain;
+       OMAPLFB_BUFFER *psBuffer;
+       OMAPLFB_VSYNC_FLIP_ITEM *psVSyncFlips;
+       IMG_UINT32 i;
+       PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+       unsigned long ulLockFlags;
+       IMG_UINT32 ui32BuffersToSkip;
+
+       PVR_UNREFERENCED_PARAMETER(ui32OEMFlags);
+       PVR_UNREFERENCED_PARAMETER(pui32SwapChainID);
+
+       if (!hDevice
+           || !psDstSurfAttrib
+           || !psSrcSurfAttrib || !ppsSyncData || !phSwapChain) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+
+       if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0) {
+               return PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       if (psDevInfo->psSwapChain != IMG_NULL) {
+               return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+       }
+
+       if (ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers) {
+               return PVRSRV_ERROR_TOOMANYBUFFERS;
+       }
+
+       if ((psDevInfo->sFBInfo.ui32RoundedBufferSize * ui32BufferCount) >
+           psDevInfo->sFBInfo.ui32FBSize) {
+               return PVRSRV_ERROR_TOOMANYBUFFERS;
+       }
+
+       ui32BuffersToSkip =
+           psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers - ui32BufferCount;
+
+       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;
+       }
+
+       PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+       psSwapChain =
+           (OMAPLFB_SWAPCHAIN *)
+           OMAPLFBAllocKernelMem(sizeof(OMAPLFB_SWAPCHAIN));
+       if (!psSwapChain) {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       psBuffer =
+           (OMAPLFB_BUFFER *) OMAPLFBAllocKernelMem(sizeof(OMAPLFB_BUFFER) *
+                                                    ui32BufferCount);
+       if (!psBuffer) {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorFreeSwapChain;
+       }
+
+       psVSyncFlips =
+           (OMAPLFB_VSYNC_FLIP_ITEM *)
+           OMAPLFBAllocKernelMem(sizeof(OMAPLFB_VSYNC_FLIP_ITEM) *
+                                 ui32BufferCount);
+       if (!psVSyncFlips) {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorFreeBuffers;
+       }
+
+       psSwapChain->ui32BufferCount = ui32BufferCount;
+       psSwapChain->psBuffer = psBuffer;
+       psSwapChain->psVSyncFlips = psVSyncFlips;
+       psSwapChain->ui32InsertIndex = 0;
+       psSwapChain->ui32RemoveIndex = 0;
+       psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
+       psSwapChain->psSwapChainLock = psDevInfo->psSwapChainLock;
+
+       for (i = 0; i < ui32BufferCount - 1; i++) {
+               psBuffer[i].psNext = &psBuffer[i + 1];
+       }
+
+       psBuffer[i].psNext = &psBuffer[0];
+
+       for (i = 0; i < ui32BufferCount; i++) {
+               IMG_UINT32 ui32SwapBuffer = i + ui32BuffersToSkip;
+               IMG_UINT32 ui32BufferOffset =
+                   ui32SwapBuffer * psDevInfo->sFBInfo.ui32RoundedBufferSize;
+
+               psBuffer[i].psSyncData = ppsSyncData[i];
+
+               psBuffer[i].sSysAddr.uiAddr =
+                   psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
+               psBuffer[i].sCPUVAddr =
+                   psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset;
+       }
+
+       for (i = 0; i < ui32BufferCount; i++) {
+               psVSyncFlips[i].bValid = IMG_FALSE;
+               psVSyncFlips[i].bFlipped = IMG_FALSE;
+               psVSyncFlips[i].bCmdCompleted = IMG_FALSE;
+       }
+#if defined (SUPPORT_TI_DSS_FW)
+       OMAPLFBEnableDisplayRegisterAccess();
+
+       psSwapChain->pvRegs =
+           ioremap(psDevInfo->psLINFBInfo->fix.mmio_start,
+                   psDevInfo->psLINFBInfo->fix.mmio_len);
+       if (psSwapChain->pvRegs == IMG_NULL) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": Couldn't map registers needed for flipping\n");
+               goto ErrorDisableDisplayRegisters;
+       }
+#endif
+       if (OMAPLFBInstallVSyncISR(psSwapChain) != PVRSRV_OK) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": ISR handler failed to register\n");
+               goto ErrorUnmapRegisters;
+       }
+
+       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       psDevInfo->psSwapChain = psSwapChain;
+
+       psSwapChain->bFlushCommands = psDevInfo->bFlushCommands;
+
+       if (psSwapChain->bFlushCommands) {
+               psSwapChain->ui32SetFlushStateRefCount = 1;
+       } else {
+               psSwapChain->ui32SetFlushStateRefCount = 0;
+               OMAPLFBEnableVSyncInterrupt(psSwapChain);
+       }
+
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       eError = EnableLFBEventNotification(psDevInfo);
+       if (eError != PVRSRV_OK) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": Couldn't enable framebuffer event notification\n");
+               goto ErrorUninstallVSyncInterrupt;
+       }
+
+       *phSwapChain = (IMG_HANDLE) psSwapChain;
+
+       return PVRSRV_OK;
+
+ErrorUninstallVSyncInterrupt:
+       if (OMAPLFBUninstallVSyncISR(psSwapChain) != PVRSRV_OK) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": Couldn't uninstall VSync ISR\n");
+       }
+ErrorUnmapRegisters:
+#if defined (SUPPORT_TI_DSS_FW)
+       iounmap(psSwapChain->pvRegs);
+ErrorDisableDisplayRegisters:
+       OMAPLFBDisableDisplayRegisterAccess();
+#endif
+       OMAPLFBFreeKernelMem(psVSyncFlips);
+ErrorFreeBuffers:
+       OMAPLFBFreeKernelMem(psBuffer);
+ErrorFreeSwapChain:
+       OMAPLFBFreeKernelMem(psSwapChain);
+
+       return eError;
+}
+
+static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
+                                      IMG_HANDLE hSwapChain)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+       OMAPLFB_SWAPCHAIN *psSwapChain;
+       unsigned long ulLockFlags;
+       PVRSRV_ERROR eError;
+
+       if (!hDevice || !hSwapChain) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+       psSwapChain = (OMAPLFB_SWAPCHAIN *) hSwapChain;
+       if (psSwapChain != psDevInfo->psSwapChain) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = DisableLFBEventNotification(psDevInfo);
+       if (eError != PVRSRV_OK) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": Couldn't disable framebuffer event notification\n");
+       }
+
+       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       OMAPLFBDisableVSyncInterrupt(psSwapChain);
+
+       FlushInternalVSyncQueue(psSwapChain);
+
+       OMAPLFBFlip(psSwapChain, psDevInfo->sFBInfo.sSysAddr.uiAddr);
+
+       psDevInfo->psSwapChain = IMG_NULL;
+
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       if (OMAPLFBUninstallVSyncISR(psSwapChain) != PVRSRV_OK) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": Couldn't uninstall VSync ISR\n");
+               return PVRSRV_ERROR_GENERIC;
+       }
+#if defined (SUPPORT_TI_DSS_FW)
+
+       iounmap(psSwapChain->pvRegs);
+
+       OMAPLFBDisableDisplayRegisterAccess();
+#endif
+
+       OMAPLFBFreeKernelMem(psSwapChain->psVSyncFlips);
+       OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
+       OMAPLFBFreeKernelMem(psSwapChain);
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
+                                IMG_HANDLE hSwapChain, IMG_RECT * psRect)
+{
+       PVR_UNREFERENCED_PARAMETER(hDevice);
+       PVR_UNREFERENCED_PARAMETER(hSwapChain);
+       PVR_UNREFERENCED_PARAMETER(psRect);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
+                                IMG_HANDLE hSwapChain, IMG_RECT * psRect)
+{
+       PVR_UNREFERENCED_PARAMETER(hDevice);
+       PVR_UNREFERENCED_PARAMETER(hSwapChain);
+       PVR_UNREFERENCED_PARAMETER(psRect);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
+                                     IMG_HANDLE hSwapChain,
+                                     IMG_UINT32 ui32CKColour)
+{
+       PVR_UNREFERENCED_PARAMETER(hDevice);
+       PVR_UNREFERENCED_PARAMETER(hSwapChain);
+       PVR_UNREFERENCED_PARAMETER(ui32CKColour);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
+                                     IMG_HANDLE hSwapChain,
+                                     IMG_UINT32 ui32CKColour)
+{
+       PVR_UNREFERENCED_PARAMETER(hDevice);
+       PVR_UNREFERENCED_PARAMETER(hSwapChain);
+       PVR_UNREFERENCED_PARAMETER(ui32CKColour);
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
+                                IMG_HANDLE hSwapChain,
+                                IMG_UINT32 * pui32BufferCount,
+                                IMG_HANDLE * phBuffer)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+       OMAPLFB_SWAPCHAIN *psSwapChain;
+       IMG_UINT32 i;
+
+       if (!hDevice || !hSwapChain || !pui32BufferCount || !phBuffer) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+       psSwapChain = (OMAPLFB_SWAPCHAIN *) hSwapChain;
+       if (psSwapChain != psDevInfo->psSwapChain) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       *pui32BufferCount = psSwapChain->ui32BufferCount;
+
+       for (i = 0; i < psSwapChain->ui32BufferCount; i++) {
+               phBuffer[i] = (IMG_HANDLE) & psSwapChain->psBuffer[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)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+
+       PVR_UNREFERENCED_PARAMETER(ui32SwapInterval);
+       PVR_UNREFERENCED_PARAMETER(hPrivateTag);
+       PVR_UNREFERENCED_PARAMETER(psClipRect);
+
+       if (!hDevice || !hBuffer || (ui32ClipRectCount != 0)) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+
+       PVR_UNREFERENCED_PARAMETER(hBuffer);
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice, IMG_HANDLE hSwapChain)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+       OMAPLFB_SWAPCHAIN *psSwapChain;
+       unsigned long ulLockFlags;
+
+       if (!hDevice || !hSwapChain) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (OMAPLFB_DEVINFO *) hDevice;
+       psSwapChain = (OMAPLFB_SWAPCHAIN *) hSwapChain;
+       if (psSwapChain != psDevInfo->psSwapChain) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       FlushInternalVSyncQueue(psSwapChain);
+
+       OMAPLFBFlip(psSwapChain, psDevInfo->sFBInfo.sSysAddr.uiAddr);
+
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       return PVRSRV_OK;
+}
+
+IMG_BOOL OMAPLFBVSyncIHandler(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+       IMG_BOOL bStatus = IMG_FALSE;
+       OMAPLFB_VSYNC_FLIP_ITEM *psFlipItem;
+       IMG_UINT32 ui32MaxIndex;
+       unsigned long ulLockFlags;
+
+       psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ui32RemoveIndex];
+       ui32MaxIndex = psSwapChain->ui32BufferCount - 1;
+
+       spin_lock_irqsave(psSwapChain->psSwapChainLock, ulLockFlags);
+
+       if (psSwapChain->bFlushCommands) {
+               goto ExitUnlock;
+       }
+
+       while (psFlipItem->bValid) {
+
+               if (psFlipItem->bFlipped) {
+
+                       if (!psFlipItem->bCmdCompleted) {
+
+                               psSwapChain->psPVRJTable->
+                                   pfnPVRSRVCmdComplete(psFlipItem->
+                                                        hCmdComplete,
+                                                        IMG_TRUE);
+
+                               psFlipItem->bCmdCompleted = IMG_TRUE;
+                       }
+
+                       psFlipItem->ui32SwapInterval--;
+
+                       if (psFlipItem->ui32SwapInterval == 0) {
+
+                               psSwapChain->ui32RemoveIndex++;
+
+                               if (psSwapChain->ui32RemoveIndex > ui32MaxIndex) {
+                                       psSwapChain->ui32RemoveIndex = 0;
+                               }
+
+                               psFlipItem->bCmdCompleted = IMG_FALSE;
+                               psFlipItem->bFlipped = IMG_FALSE;
+
+                               psFlipItem->bValid = IMG_FALSE;
+                       } else {
+
+                               break;
+                       }
+               } else {
+
+                       OMAPLFBFlip(psSwapChain,
+                                   (IMG_UINT32) psFlipItem->sSysAddr);
+
+                       psFlipItem->bFlipped = IMG_TRUE;
+
+                       break;
+               }
+
+               psFlipItem =
+                   &psSwapChain->psVSyncFlips[psSwapChain->ui32RemoveIndex];
+       }
+
+ExitUnlock:
+       spin_unlock_irqrestore(psSwapChain->psSwapChainLock, ulLockFlags);
+       return bStatus;
+}
+
+static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie,
+                           IMG_UINT32 ui32DataSize, IMG_VOID * pvData)
+{
+       DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+       OMAPLFB_DEVINFO *psDevInfo;
+       OMAPLFB_BUFFER *psBuffer;
+       OMAPLFB_SWAPCHAIN *psSwapChain;
+#if defined(SYS_USING_INTERRUPTS)
+       OMAPLFB_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 = (OMAPLFB_DEVINFO *) psFlipCmd->hExtDevice;
+
+       psBuffer = (OMAPLFB_BUFFER *) psFlipCmd->hExtBuffer;
+       psSwapChain = (OMAPLFB_SWAPCHAIN *) psFlipCmd->hExtSwapChain;
+
+       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       if (psDevInfo->bDeviceSuspended) {
+               psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie,
+                                                              IMG_TRUE);
+               goto ExitTrueUnlock;
+       }
+#if defined(SYS_USING_INTERRUPTS)
+
+       if (psFlipCmd->ui32SwapInterval == 0 || psSwapChain->bFlushCommands) {
+#endif
+
+               OMAPLFBFlip(psSwapChain, psBuffer->sSysAddr.uiAddr);
+
+               psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie,
+                                                              IMG_TRUE);
+
+#if defined(SYS_USING_INTERRUPTS)
+               goto ExitTrueUnlock;
+       }
+
+       psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ui32InsertIndex];
+
+       if (!psFlipItem->bValid) {
+               IMG_UINT32 ui32MaxIndex = psSwapChain->ui32BufferCount - 1;
+
+               if (psSwapChain->ui32InsertIndex ==
+                   psSwapChain->ui32RemoveIndex) {
+
+                       OMAPLFBFlip(psSwapChain, psBuffer->sSysAddr.uiAddr);
+
+                       psFlipItem->bFlipped = IMG_TRUE;
+               } else {
+                       psFlipItem->bFlipped = IMG_FALSE;
+               }
+
+               psFlipItem->hCmdComplete = hCmdCookie;
+               psFlipItem->ui32SwapInterval = psFlipCmd->ui32SwapInterval;
+               psFlipItem->sSysAddr = &psBuffer->sSysAddr;
+               psFlipItem->bValid = IMG_TRUE;
+
+               psSwapChain->ui32InsertIndex++;
+               if (psSwapChain->ui32InsertIndex > ui32MaxIndex) {
+                       psSwapChain->ui32InsertIndex = 0;
+               }
+
+               goto ExitTrueUnlock;
+       }
+
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+       return IMG_FALSE;
+#endif
+
+ExitTrueUnlock:
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+       return IMG_TRUE;
+}
+
+static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo)
+{
+       struct fb_info *psLINFBInfo;
+       struct module *psLINFBOwner;
+       OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+       PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+       unsigned long FBSize;
+
+       acquire_console_sem();
+
+       if (fb_idx < 0 || fb_idx >= num_registered_fb) {
+               eError = PVRSRV_ERROR_INVALID_DEVICE;
+               goto errRelSem;
+       }
+
+       psLINFBInfo = registered_fb[fb_idx];
+
+       psLINFBOwner = psLINFBInfo->fbops->owner;
+       if (!try_module_get(psLINFBOwner)) {
+               printk(KERN_INFO DRIVER_PREFIX
+                      ": Couldn't get framebuffer module\n");
+
+               goto errRelSem;
+       }
+
+       if (psLINFBInfo->fbops->fb_open != NULL) {
+               int res;
+
+               res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
+               if (res != 0) {
+                       printk(KERN_INFO DRIVER_PREFIX
+                              ": Couldn't open framebuffer: %d\n", res);
+
+                       goto errModPut;
+               }
+       }
+
+       psDevInfo->psLINFBInfo = psLINFBInfo;
+
+       FBSize = (psLINFBInfo->screen_size) != 0 ?
+           psLINFBInfo->screen_size : psLINFBInfo->fix.smem_len;
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": Framebuffer physical address: 0x%lx\n",
+                     psLINFBInfo->fix.smem_start));
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": Framebuffer virtual address: 0x%lx\n",
+                     (unsigned long)psLINFBInfo->screen_base));
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": Framebuffer size: %lu\n", FBSize));
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": Framebuffer virtual width: %u\n",
+                     psLINFBInfo->var.xres_virtual));
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": Framebuffer virtual height: %u\n",
+                     psLINFBInfo->var.yres_virtual));
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": Framebuffer width: %u\n", psLINFBInfo->var.xres));
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": Framebuffer height: %u\n", psLINFBInfo->var.yres));
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": Framebuffer stride: %u\n",
+                     psLINFBInfo->fix.line_length));
+
+       psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
+       psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
+
+       psPVRFBInfo->ui32Width = psLINFBInfo->var.xres;
+       psPVRFBInfo->ui32Height = psLINFBInfo->var.yres;
+       psPVRFBInfo->ui32ByteStride = psLINFBInfo->fix.line_length;
+       psPVRFBInfo->ui32FBSize = FBSize;
+       psPVRFBInfo->ui32BufferSize =
+           psPVRFBInfo->ui32Height * psPVRFBInfo->ui32ByteStride;
+
+       psPVRFBInfo->ui32RoundedBufferSize =
+           OMAPLFB_PAGE_ROUNDUP(psPVRFBInfo->ui32BufferSize);
+
+       if (psLINFBInfo->var.bits_per_pixel == 16) {
+               if ((psLINFBInfo->var.red.length == 5) &&
+                   (psLINFBInfo->var.green.length == 6) &&
+                   (psLINFBInfo->var.blue.length == 5) &&
+                   (psLINFBInfo->var.red.offset == 11) &&
+                   (psLINFBInfo->var.green.offset == 5) &&
+                   (psLINFBInfo->var.blue.offset == 0) &&
+                   (psLINFBInfo->var.red.msb_right == 0)) {
+                       printk("PVRSRV_PIXEL_FORMAT_RGB565\n");
+                       psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
+               } else {
+                       printk("Unknown FB format\n");
+               }
+       } else {
+               if (psLINFBInfo->var.bits_per_pixel == 32) {
+                       if ((psLINFBInfo->var.red.length == 8) &&
+                           (psLINFBInfo->var.green.length == 8) &&
+                           (psLINFBInfo->var.blue.length == 8) &&
+                           (psLINFBInfo->var.transp.length == 8) &&
+                           (psLINFBInfo->var.red.offset == 16) &&
+                           (psLINFBInfo->var.green.offset == 8) &&
+                           (psLINFBInfo->var.blue.offset == 0) &&
+                           (psLINFBInfo->var.transp.offset == 24) &&
+                           (psLINFBInfo->var.red.msb_right == 0)) {
+                               printk("PVRSRV_PIXEL_FORMAT_ARGB8888\n");
+                               psPVRFBInfo->ePixelFormat =
+                                   PVRSRV_PIXEL_FORMAT_ARGB8888;
+                       } else {
+                               if ((psLINFBInfo->var.red.length == 8) &&
+                                   (psLINFBInfo->var.green.length == 8) &&
+                                   (psLINFBInfo->var.blue.length == 8) &&
+                                   (psLINFBInfo->var.transp.length == 0) &&
+                                   (psLINFBInfo->var.red.offset == 16) &&
+                                   (psLINFBInfo->var.green.offset == 8) &&
+                                   (psLINFBInfo->var.blue.offset == 0) &&
+                                   (psLINFBInfo->var.transp.offset == 0) &&
+                                   (psLINFBInfo->var.red.msb_right == 0)) {
+                                       printk("PVRSRV_PIXEL_FORMAT_RGB888\n");
+                                       printk
+                                           ("EGL library does not support RGB888 !!!\n");
+                                       psPVRFBInfo->ePixelFormat =
+                                           PVRSRV_PIXEL_FORMAT_RGB888;
+                               } else {
+                                       printk("Unknown FB format\n");
+                               }
+                       }
+               } else {
+                       printk("Unknown FB format\n");
+               }
+       }
+
+       psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
+       psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
+
+       eError = PVRSRV_OK;
+       goto errRelSem;
+
+errModPut:
+       module_put(psLINFBOwner);
+errRelSem:
+       release_console_sem();
+       return eError;
+}
+
+static IMG_VOID DeInitDev(OMAPLFB_DEVINFO * psDevInfo)
+{
+       struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
+       struct module *psLINFBOwner;
+
+       acquire_console_sem();
+
+       psLINFBOwner = psLINFBInfo->fbops->owner;
+
+       if (psLINFBInfo->fbops->fb_release != NULL) {
+               (void)psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
+       }
+
+       module_put(psLINFBOwner);
+
+       release_console_sem();
+}
+
+PVRSRV_ERROR OMAPLFBInit(IMG_VOID)
+{
+       OMAPLFB_DEVINFO *psDevInfo;
+
+       psDevInfo = GetAnchorPtr();
+
+       if (psDevInfo == IMG_NULL) {
+               PFN_CMD_PROC pfnCmdProcList[OMAPLFB_COMMAND_COUNT];
+               IMG_UINT32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
+
+               psDevInfo =
+                   (OMAPLFB_DEVINFO *)
+                   OMAPLFBAllocKernelMem(sizeof(OMAPLFB_DEVINFO));
+
+               if (!psDevInfo) {
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+
+               memset(psDevInfo, 0, sizeof(OMAPLFB_DEVINFO));
+
+               SetAnchorPtr((IMG_VOID *) psDevInfo);
+
+               psDevInfo->ui32RefCount = 0;
+
+               if (InitDev(psDevInfo) != PVRSRV_OK) {
+                       return PVRSRV_ERROR_INIT_FAILURE;
+               }
+
+               if (OMAPLFBGetLibFuncAddr
+                   ("PVRGetDisplayClassJTable",
+                    &pfnGetPVRJTable) != PVRSRV_OK) {
+                       return PVRSRV_ERROR_INIT_FAILURE;
+               }
+
+               if (!(*pfnGetPVRJTable) (&psDevInfo->sPVRJTable)) {
+                       return PVRSRV_ERROR_INIT_FAILURE;
+               }
+
+               spin_lock_init(psDevInfo->psSwapChainLock);
+
+               psDevInfo->psSwapChain = IMG_NULL;
+               psDevInfo->bFlushCommands = IMG_FALSE;
+               psDevInfo->bDeviceSuspended = IMG_FALSE;
+               psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers =
+                   psDevInfo->sFBInfo.ui32FBSize /
+                   psDevInfo->sFBInfo.ui32RoundedBufferSize;
+#if !defined (SUPPORT_TI_DSS_FW)
+               /* DSS2 have trouble with ui32MaxSwapChainBuffers > 3 */
+               if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers > 3)
+                       psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 3;
+#endif
+               if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0) {
+                       psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0;
+                       psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0;
+               } else {
+                       psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
+                       psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
+               }
+               psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;
+
+               strncpy(psDevInfo->sDisplayInfo.szDisplayName,
+                       DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
+
+               psDevInfo->sDisplayFormat.pixelformat =
+                   psDevInfo->sFBInfo.ePixelFormat;
+               psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width;
+               psDevInfo->sDisplayDim.ui32Height =
+                   psDevInfo->sFBInfo.ui32Height;
+               psDevInfo->sDisplayDim.ui32ByteStride =
+                   psDevInfo->sFBInfo.ui32ByteStride;
+
+               DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                             ": Maximum number of swap chain buffers: %lu\n",
+                             psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
+
+               psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
+               psDevInfo->sSystemBuffer.sCPUVAddr =
+                   psDevInfo->sFBInfo.sCPUVAddr;
+               psDevInfo->sSystemBuffer.ui32BufferSize =
+                   (psDevInfo->sFBInfo.ui32RoundedBufferSize);
+
+               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->ui32DeviceID) !=
+                   PVRSRV_OK) {
+                       return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
+               }
+
+               pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
+
+               aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
+               aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
+
+               if (psDevInfo->sPVRJTable.
+                   pfnPVRSRVRegisterCmdProcList(psDevInfo->ui32DeviceID,
+                                                &pfnCmdProcList[0],
+                                                aui32SyncCountList,
+                                                OMAPLFB_COMMAND_COUNT) !=
+                   PVRSRV_OK) {
+                       printk(KERN_WARNING DRIVER_PREFIX
+                              ": Can't register callback\n");
+                       return PVRSRV_ERROR_CANT_REGISTER_CALLBACK;
+               }
+
+       }
+
+       psDevInfo->ui32RefCount++;
+
+       return PVRSRV_OK;
+
+}
+
+PVRSRV_ERROR OMAPLFBDeinit(IMG_VOID)
+{
+       OMAPLFB_DEVINFO *psDevInfo, *psDevFirst;
+
+       psDevFirst = GetAnchorPtr();
+       psDevInfo = psDevFirst;
+
+       if (psDevInfo == IMG_NULL) {
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       psDevInfo->ui32RefCount--;
+
+       if (psDevInfo->ui32RefCount == 0) {
+
+               PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable = &psDevInfo->sPVRJTable;
+
+               if (psDevInfo->sPVRJTable.
+                   pfnPVRSRVRemoveCmdProcList(psDevInfo->ui32DeviceID,
+                                              OMAPLFB_COMMAND_COUNT) !=
+                   PVRSRV_OK) {
+                       return PVRSRV_ERROR_GENERIC;
+               }
+
+               if (psJTable->
+                   pfnPVRSRVRemoveDCDevice(psDevInfo->ui32DeviceID) !=
+                   PVRSRV_OK) {
+                       return PVRSRV_ERROR_GENERIC;
+               }
+
+               DeInitDev(psDevInfo);
+
+               OMAPLFBFreeKernelMem(psDevInfo);
+       }
+
+       SetAnchorPtr(IMG_NULL);
+
+       return PVRSRV_OK;
+}
+
+#if defined(LDM_PLATFORM)
+IMG_VOID OMAPLFBDriverSuspend(IMG_VOID)
+{
+       OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       unsigned long ulLockFlags;
+
+       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       if (psDevInfo->bDeviceSuspended) {
+               goto ExitUnlock;
+       }
+       psDevInfo->bDeviceSuspended = IMG_TRUE;
+
+       SetFlushStateInternalNoLock(psDevInfo, IMG_TRUE);
+
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+
+#if defined (SUPPORT_TI_DSS_FW)
+       if (psDevInfo->psSwapChain != IMG_NULL) {
+               OMAPLFBDisableDisplayRegisterAccess();
+       }
+#endif
+       return;
+
+ExitUnlock:
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+}
+
+IMG_VOID OMAPLFBDriverResume(IMG_VOID)
+{
+       OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+       unsigned long ulLockFlags;
+
+       if (!psDevInfo->bDeviceSuspended) {
+               return;
+       }
+#if defined (SUPPORT_TI_DSS_FW)
+       if (psDevInfo->psSwapChain != IMG_NULL) {
+               OMAPLFBEnableDisplayRegisterAccess();
+       }
+#endif
+       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+       SetFlushStateInternalNoLock(psDevInfo, IMG_FALSE);
+
+       psDevInfo->bDeviceSuspended = IMG_FALSE;
+
+       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+}
+#endif
diff --git a/pvr/omaplfb_linux.c b/pvr/omaplfb_linux.c
new file mode 100644 (file)
index 0000000..fa96a19
--- /dev/null
@@ -0,0 +1,373 @@
+/**********************************************************************
+ *
+ * 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 AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+
+#if defined(LDM_PLATFORM)
+#include <linux/platform_device.h>
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "omaplfb.h"
+#include "pvrmodule.h"
+
+#if defined (SUPPORT_TI_DSS_FW)
+#include <asm/io.h>
+#include <asm/arch-omap/display.h>
+#else
+#if !defined (CONFIG_OMAP2_DSS)
+#define DISPC_IRQ_VSYNC 0x0002
+extern int omap_dispc_request_irq(unsigned long, void (*)(void *), void *);
+extern void omap_dispc_free_irq(unsigned long, void (*)(void *), void *);
+extern void omap_dispc_set_plane_base(int plane, IMG_UINT32 phys_addr);
+#else
+#include <mach/display.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#endif
+#endif
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+#define unref__ __attribute__ ((unused))
+
+IMG_VOID *OMAPLFBAllocKernelMem(IMG_UINT32 ui32Size)
+{
+       return kmalloc(ui32Size, GFP_KERNEL);
+}
+
+IMG_VOID OMAPLFBFreeKernelMem(IMG_VOID * pvMem)
+{
+       kfree(pvMem);
+}
+
+PVRSRV_ERROR OMAPLFBGetLibFuncAddr(IMG_CHAR * szFunctionName,
+                                  PFN_DC_GET_PVRJTABLE * ppfnFuncTable)
+{
+       if (strcmp("PVRGetDisplayClassJTable", szFunctionName) != 0)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       *ppfnFuncTable = PVRGetDisplayClassJTable;
+
+       return PVRSRV_OK;
+}
+
+#if !defined (SUPPORT_TI_DSS_FW)
+IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+       OMAPLFBInstallVSyncISR(psSwapChain);
+}
+
+IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+       OMAPLFBUninstallVSyncISR(psSwapChain);
+}
+#else
+static IMG_VOID OMAPLFBVSyncWriteReg(OMAPLFB_SWAPCHAIN * psSwapChain,
+                                    IMG_UINT32 ui32Offset,
+                                    IMG_UINT32 ui32Value)
+{
+       IMG_VOID *pvRegAddr =
+           (IMG_VOID *) ((IMG_UINT8 *) psSwapChain->pvRegs + ui32Offset);
+
+       writel(ui32Value, pvRegAddr);
+}
+
+static IMG_UINT32 OMAPLFBVSyncReadReg(OMAPLFB_SWAPCHAIN * psSwapChain,
+                                     IMG_UINT32 ui32Offset)
+{
+       return readl((IMG_UINT8 *) psSwapChain->pvRegs + ui32Offset);
+}
+
+IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+#if defined(SYS_USING_INTERRUPTS)
+
+       IMG_UINT32 ui32InterruptEnable =
+           OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_IRQENABLE);
+       ui32InterruptEnable |= OMAPLCD_INTMASK_VSYNC;
+       OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_IRQENABLE,
+                            ui32InterruptEnable);
+#endif
+}
+
+IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+#if defined(SYS_USING_INTERRUPTS)
+
+       IMG_UINT32 ui32InterruptEnable =
+           OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_IRQENABLE);
+       ui32InterruptEnable &= ~(OMAPLCD_INTMASK_VSYNC);
+       OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_IRQENABLE,
+                            ui32InterruptEnable);
+#endif
+}
+#endif
+#if defined(SYS_USING_INTERRUPTS)
+static void
+#if defined (SUPPORT_TI_DSS_FW)
+OMAPLFBVSyncISR(void *arg, struct pt_regs unref__ * regs)
+#else
+#if defined (CONFIG_OMAP2_DSS)
+OMAPLFBVSyncISR(void *arg, u32 mask)
+#else
+OMAPLFBVSyncISR(void *arg)
+#endif
+#endif
+{
+       OMAPLFB_SWAPCHAIN *psSwapChain = (OMAPLFB_SWAPCHAIN *) arg;
+
+       (void)OMAPLFBVSyncIHandler(psSwapChain);
+}
+#endif
+
+#if !defined (SUPPORT_TI_DSS_FW)
+PVRSRV_ERROR OMAPLFBInstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+#if !defined (CONFIG_OMAP2_DSS)
+       if (omap_dispc_request_irq
+           (DISPC_IRQ_VSYNC, OMAPLFBVSyncISR, psSwapChain) != 0)
+#else
+       if (omap_dispc_register_isr
+           ((omap_dispc_isr_t) OMAPLFBVSyncISR, psSwapChain,
+            DISPC_IRQ_VSYNC) != 0)
+#endif
+               return PVRSRV_ERROR_OUT_OF_MEMORY;      /* not worth a proper mapping */
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+#if !defined (CONFIG_OMAP2_DSS)
+       omap_dispc_free_irq(DISPC_IRQ_VSYNC, OMAPLFBVSyncISR, psSwapChain);
+#else
+       omap_dispc_unregister_isr(OMAPLFBVSyncISR);
+#endif
+       return PVRSRV_OK;
+}
+
+IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr)
+{
+#if !defined (CONFIG_OMAP2_DSS)
+       omap_dispc_set_plane_base(0, aPhyAddr);
+#else
+       OMAPLFBFlipDSS2(psSwapChain, aPhyAddr);
+#endif
+}
+#else
+PVRSRV_ERROR OMAPLFBInstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+#if defined(SYS_USING_INTERRUPTS)
+       OMAPLFBDisableVSyncInterrupt(psSwapChain);
+
+       if (omap2_disp_register_isr(OMAPLFBVSyncISR, psSwapChain,
+                                   DISPC_IRQSTATUS_VSYNC)) {
+               printk(KERN_INFO DRIVER_PREFIX
+                      ": OMAPLFBInstallVSyncISR: Request OMAPLCD IRQ failed\n");
+               return PVRSRV_ERROR_INIT_FAILURE;
+       }
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain)
+{
+#if defined(SYS_USING_INTERRUPTS)
+       OMAPLFBDisableVSyncInterrupt(psSwapChain);
+
+       omap2_disp_unregister_isr(OMAPLFBVSyncISR);
+
+#endif
+       return PVRSRV_OK;
+}
+
+IMG_VOID OMAPLFBEnableDisplayRegisterAccess(IMG_VOID)
+{
+       omap2_disp_get_dss();
+}
+
+IMG_VOID OMAPLFBDisableDisplayRegisterAccess(IMG_VOID)
+{
+       omap2_disp_put_dss();
+}
+
+IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr)
+{
+       IMG_UINT32 control;
+
+       OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_GFX_BA0, aPhyAddr);
+       OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_GFX_BA1, aPhyAddr);
+
+       control = OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_CONTROL);
+       control |= OMAP_CONTROL_GOLCD;
+       OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_CONTROL, control);
+}
+#endif
+
+#if defined(LDM_PLATFORM)
+
+static IMG_BOOL bDeviceSuspended;
+
+static void OMAPLFBCommonSuspend(void)
+{
+       if (bDeviceSuspended) {
+               return;
+       }
+
+       OMAPLFBDriverSuspend();
+
+       bDeviceSuspended = IMG_TRUE;
+}
+
+static int OMAPLFBDriverSuspend_Entry(struct platform_device unref__ * pDevice,
+                                     pm_message_t unref__ state)
+{
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": OMAPLFBDriverSuspend_Entry\n"));
+
+       OMAPLFBCommonSuspend();
+
+       return 0;
+}
+
+static int OMAPLFBDriverResume_Entry(struct platform_device unref__ * pDevice)
+{
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": OMAPLFBDriverResume_Entry\n"));
+
+       OMAPLFBDriverResume();
+
+       bDeviceSuspended = IMG_FALSE;
+
+       return 0;
+}
+
+static void OMAPLFBDriverShutdown_Entry(struct platform_device unref__ *
+                                       pDevice)
+{
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": OMAPLFBDriverShutdown_Entry\n"));
+
+       OMAPLFBCommonSuspend();
+}
+
+static void OMAPLFBDeviceRelease_Entry(struct device unref__ * pDevice)
+{
+       DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+                     ": OMAPLFBDriverRelease_Entry\n"));
+
+       OMAPLFBCommonSuspend();
+}
+
+static struct platform_driver omaplfb_driver = {
+       .driver = {
+                  .name = DRVNAME,
+                  },
+       .suspend = OMAPLFBDriverSuspend_Entry,
+       .resume = OMAPLFBDriverResume_Entry,
+       .shutdown = OMAPLFBDriverShutdown_Entry,
+};
+
+static struct platform_device omaplfb_device = {
+       .name = DEVNAME,
+       .id = -1,
+       .dev = {
+               .release = OMAPLFBDeviceRelease_Entry}
+};
+#endif
+
+static int __init OMAPLFB_Init(void)
+{
+#if defined(LDM_PLATFORM)
+       int error;
+#endif
+
+       if (OMAPLFBInit() != PVRSRV_OK) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": OMAPLFB_Init: OMAPLFBInit failed\n");
+               return -ENODEV;
+       }
+#if defined(LDM_PLATFORM)
+       if ((error = platform_driver_register(&omaplfb_driver)) != 0) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": OMAPLFB_Init: Unable to register platform driver (%d)\n",
+                      error);
+
+               goto ExitDeinit;
+       }
+
+       if ((error = platform_device_register(&omaplfb_device)) != 0) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": OMAPLFB_Init:  Unable to register platform device (%d)\n",
+                      error);
+
+               goto ExitDriverUnregister;
+       }
+#endif
+
+       return 0;
+
+#if defined(LDM_PLATFORM)
+ExitDriverUnregister:
+       platform_driver_unregister(&omaplfb_driver);
+
+ExitDeinit:
+       if (OMAPLFBDeinit() != PVRSRV_OK) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": OMAPLFB_Init: OMAPLFBDeinit failed\n");
+       }
+
+       return -ENODEV;
+#endif
+}
+
+static void __exit OMAPLFB_Cleanup(void)
+{
+#if defined (LDM_PLATFORM)
+       platform_device_unregister(&omaplfb_device);
+       platform_driver_unregister(&omaplfb_driver);
+#endif
+
+       if (OMAPLFBDeinit() != PVRSRV_OK) {
+               printk(KERN_WARNING DRIVER_PREFIX
+                      ": OMAPLFB_Cleanup: OMAPLFBDeinit failed\n");
+       }
+}
+
+module_init(OMAPLFB_Init);
+module_exit(OMAPLFB_Cleanup);
diff --git a/pvr/osfunc.c b/pvr/osfunc.c
new file mode 100644 (file)
index 0000000..8370e1a
--- /dev/null
@@ -0,0 +1,2161 @@
+/**********************************************************************
+ *
+ * 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 AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#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/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 "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"
+
+#define EVENT_OBJECT_TIMEOUT_MS                (100)
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#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(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
+                       IMG_PVOID * ppvCpuVAddr, IMG_HANDLE * phBlockAlloc)
+#else
+PVRSRV_ERROR _OSAllocMem(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 !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSFreeMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
+                      IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+#else
+PVRSRV_ERROR _OSFreeMem(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(IMG_UINT32 ui32AllocFlags,
+            IMG_UINT32 ui32Size,
+            IMG_VOID ** ppvCpuVAddr, IMG_HANDLE * phOSMemHandle)
+{
+       LinuxMemArea *psLinuxMemArea;
+
+#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("Import Arena", psLinuxMemArea,
+                                           ui32AllocFlags);
+                       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("Import Arena", psLinuxMemArea,
+                                           ui32AllocFlags);
+                       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;
+       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 = PVRSRV_OK;
+
+       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;
+       }
+
+       if (psParentLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO) {
+               eError = PVRMMapRegisterArea("Physical", psLinuxMemArea, 0);
+               if (eError != PVRSRV_OK) {
+                       goto failed_register_area;
+               }
+       } else if (psParentLinuxMemArea->eAreaType ==
+                  LINUX_MEM_AREA_ALLOC_PAGES) {
+               eError = PVRMMapRegisterArea("Import Arena", psLinuxMemArea, 0);
+               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 *psParentLinuxMemArea, *psLinuxMemArea;
+       PVRSRV_ERROR eError;
+
+       psLinuxMemArea = (LinuxMemArea *) hOSMemHandle;
+       PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+       psParentLinuxMemArea =
+           psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+
+       if (!(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+           && (psParentLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO
+               || psParentLinuxMemArea->eAreaType ==
+               LINUX_MEM_AREA_ALLOC_PAGES)
+           ) {
+               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)
+       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_VOID OSMemSet(IMG_VOID * pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMSET)
+       unsigned char *Buff;
+       int i;
+
+       Buff = (unsigned char *)pvDest;
+       for (i = 0; i < ui32Size; i++) {
+               Buff[i] = ui8Value;
+       }
+#else
+       memset(pvDest, (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) != 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) != 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, 0x1000, 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)
+{
+       unsigned long 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;
+       }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+       return current->pgrp;
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+       return task_tgid_nr(current);
+#else
+       return 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;
+
+#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) {
+               SYS_DATA *psSysData = psDeviceNode->psSysData;
+               ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
+
+               tasklet_schedule(&psEnvData->sMISRTasklet);
+       }
+
+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;
+
+#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) {
+               ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
+
+               tasklet_schedule(&psEnvData->sMISRTasklet);
+       }
+
+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 %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,
+#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_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,
+#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_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;
+}
+
+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
+
+#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_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 =
+                   IORemapWrapper(BasePAddr, 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)"));
+               *phOSMemHandle = (IMG_HANDLE) 0;
+               return NULL;
+       }
+
+       PVR_ASSERT(0);
+       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);
+
+       if (ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) {
+               IOUnmapWrapper(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;
+       }
+
+       PVR_ASSERT(0);
+       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("Physical", psLinuxMemArea,
+                                           ui32MappingFlags);
+                       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("Physical", psLinuxMemArea,
+                                           ui32MappingFlags);
+                       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;
+
+       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;
+
+       PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+
+       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 =
+                           NewIORemapLinuxMemArea(BasePAddr, ui32Bytes,
+                                                  ui32MappingFlags);
+                       if (!psLinuxMemArea) {
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+                       break;
+               }
+       case PVRSRV_HAP_SINGLE_PROCESS:
+               {
+
+                       psLinuxMemArea =
+                           NewIOLinuxMemArea(BasePAddr, ui32Bytes,
+                                             ui32MappingFlags);
+                       if (!psLinuxMemArea) {
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+                       PVRMMapRegisterArea("Physical", psLinuxMemArea,
+                                           ui32MappingFlags);
+                       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_GENERIC;
+                       }
+                       PVRMMapRegisterArea("Physical", psLinuxMemArea,
+                                           ui32MappingFlags);
+                       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);
+
+       LinuxMemAreaRegister(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);
+
+       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
+       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);
+
+       PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
+#else
+       PVR_UNREFERENCED_PARAMETER(ui32Size);
+       PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+
+       KFreeWrapper(pvLinAddr);
+#endif
+       return PVRSRV_OK;
+}
+
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+       return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
+#else
+       return *(IMG_UINT32 *) (pvLinRegBaseAddr + ui32Offset);
+#endif
+}
+
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset,
+                     IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+       writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+#else
+       *(IMG_UINT32 *) (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) != 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);
+
+       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, 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, 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;
+               }
+       }
+
+       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_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_GENERIC;
+       default:
+               PVR_DPF((PVR_DBG_ERROR,
+                        "OSPCIResumeDev: pci_set_power_state failed (%d)",
+                        err));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       err = pci_restore_state(psPVRPCI->psPCIDev);
+       if (err != 0) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "OSPCIResumeDev: pci_restore_state failed (%d)", err));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       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;
+}
+
+#endif
+
+typedef struct TIMER_CALLBACK_DATA_TAG {
+       PFN_TIMER_FUNC pfnTimerFunc;
+       IMG_VOID *pvData;
+       struct timer_list sTimer;
+       IMG_UINT32 ui32Delay;
+       IMG_BOOL bActive;
+} TIMER_CALLBACK_DATA;
+
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
+{
+       TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA *) ui32Data;
+
+       if (!psTimerCBData->bActive)
+               return;
+
+       psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+
+       mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID * pvData,
+                     IMG_UINT32 ui32MsTimeout)
+{
+       TIMER_CALLBACK_DATA *psTimerCBData;
+
+       if (!pfnTimerFunc) {
+               PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
+               return IMG_NULL;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                      sizeof(TIMER_CALLBACK_DATA),
+                      (IMG_VOID **) & psTimerCBData, IMG_NULL) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "OSAddTimer: failed to allocate memory for TIMER_CALLBACK_DATA"));
+               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 = OSTimerCallbackWrapper;
+       psTimerCBData->sTimer.data = (IMG_UINT32) psTimerCBData;
+       psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+       return (IMG_HANDLE) psTimerCBData;
+}
+
+PVRSRV_ERROR OSRemoveTimer(IMG_HANDLE hTimer)
+{
+       TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA *) hTimer;
+
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(TIMER_CALLBACK_DATA),
+                 psTimerCBData, IMG_NULL);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSEnableTimer(IMG_HANDLE hTimer)
+{
+       TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA *) hTimer;
+
+       psTimerCBData->bActive = IMG_TRUE;
+
+       add_timer(&psTimerCBData->sTimer);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSDisableTimer(IMG_HANDLE hTimer)
+{
+       TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA *) hTimer;
+
+       psTimerCBData->bActive = IMG_FALSE;
+
+       del_timer_sync(&psTimerCBData->sTimer);
+
+       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 = PVRSRV_OK;
+
+       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 = PVRSRV_OK;
+
+       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;
+}
+
+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)
+{
+       int linuxType;
+
+       if (eVerification == PVR_VERIFY_READ)
+               linuxType = VERIFY_READ;
+       else if (eVerification == PVR_VERIFY_WRITE)
+               linuxType = VERIFY_WRITE;
+       else {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Unknown eVerification",
+                        __FUNCTION__));
+               return PVRSRV_ERROR_GENERIC;
+       }
+       return (IMG_BOOL) 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;
+       int iNumPages;
+       struct page **ppsPages;
+       IMG_SYS_PHYADDR *psPhysAddr;
+       int iPageOffset;
+       int iContiguous;
+#if defined(DEBUG)
+       unsigned long ulStartAddr;
+       unsigned long ulBeyondEndAddr;
+       struct vm_area_struct *psVMArea;
+#endif
+} sWrapMemInfo;
+
+static void CheckPagesContiguous(sWrapMemInfo * psInfo)
+{
+       unsigned ui;
+       IMG_UINT32 ui32AddrChk;
+
+       BUG_ON(psInfo == IMG_NULL);
+
+       psInfo->iContiguous = 1;
+
+       for (ui = 0, ui32AddrChk = psInfo->psPhysAddr[0].uiAddr;
+            ui < psInfo->iNumPages; ui++, ui32AddrChk += PAGE_SIZE) {
+               if (psInfo->psPhysAddr[ui].uiAddr != ui32AddrChk) {
+                       psInfo->iContiguous = 0;
+                       break;
+               }
+       }
+}
+
+static struct page *CPUVAddrToPage(struct vm_area_struct *psVMArea,
+                                  unsigned long ulCPUVAddr)
+{
+#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;
+       unsigned long 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_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
+       if (pte_none(*psPTE) || !pte_present(*psPTE) || !pte_write(*psPTE))
+               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;
+#else
+       return NULL;
+#endif
+}
+
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+       sWrapMemInfo *psInfo = (sWrapMemInfo *) hOSWrapMem;
+       unsigned ui;
+
+       BUG_ON(psInfo == IMG_NULL);
+
+#if defined(DEBUG)
+       switch (psInfo->eType) {
+       case WRAP_TYPE_FIND_VMA_PAGES:
+
+       case WRAP_TYPE_FIND_VMA_PFN:
+               {
+                       struct vm_area_struct *psVMArea;
+
+                       down_read(&current->mm->mmap_sem);
+
+                       psVMArea = find_vma(current->mm, psInfo->ulStartAddr);
+                       if (psVMArea == NULL) {
+                               printk(KERN_WARNING
+                                      ": OSCpuVToPageListRelease: Couldn't find memory region containing start address %lx",
+                                      psInfo->ulStartAddr);
+
+                               up_read(&current->mm->mmap_sem);
+                               break;
+                       }
+
+                       if (psInfo->psVMArea != psVMArea) {
+                               printk(KERN_WARNING
+                                      ": OSCpuVToPageListRelease: vm_area_struct has a different address from the one used in ImportMem (%p != %p)",
+                                      psVMArea, psInfo->psVMArea);
+                       }
+
+                       if (psInfo->ulStartAddr < psVMArea->vm_start) {
+                               printk(KERN_WARNING
+                                      ": OSCpuVToPageListRelease: Start address %lx is outside of the region returned by find_vma",
+                                      psInfo->ulStartAddr);
+                       }
+
+                       if (psInfo->ulBeyondEndAddr > psVMArea->vm_end) {
+                               printk(KERN_WARNING
+                                      ": OSCpuVToPageListRelease: End address %lx is outside of the region returned by find_vma",
+                                      psInfo->ulBeyondEndAddr);
+                       }
+
+                       if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) !=
+                           (VM_IO | VM_RESERVED)) {
+                               printk(KERN_WARNING
+                                      ": OSCpuVToPageListRelease: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)",
+                                      psVMArea->vm_flags);
+                       }
+
+                       if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) !=
+                           (VM_READ | VM_WRITE)) {
+                               printk(KERN_WARNING
+                                      ": OSCpuVToPageListRelease: OSWrapMemReleasePages: No read/write access to memory region (VMA flags: 0x%lx)",
+                                      psVMArea->vm_flags);
+                       }
+
+                       up_read(&current->mm->mmap_sem);
+                       break;
+               }
+       default:
+               break;
+       }
+#endif
+
+       switch (psInfo->eType) {
+       case WRAP_TYPE_CLEANUP:
+               break;
+       case WRAP_TYPE_FIND_VMA_PFN:
+               break;
+       case WRAP_TYPE_GET_USER_PAGES:
+               {
+                       for (ui = 0; ui < psInfo->iNumPages; ui++) {
+                               struct page *psPage = psInfo->ppsPages[ui];
+
+                               if (!PageReserved(psPage)) ;
+                               {
+                                       SetPageDirty(psPage);
+                               }
+                               page_cache_release(psPage);
+                       }
+                       break;
+               }
+       case WRAP_TYPE_FIND_VMA_PAGES:
+               {
+                       for (ui = 0; ui < psInfo->iNumPages; ui++) {
+                               put_page_testzero(psInfo->ppsPages[ui]);
+                       }
+                       break;
+               }
+       default:
+               {
+                       printk(KERN_WARNING
+                              ": OSCpuVToPageListRelease: 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)
+{
+       unsigned long ulStartAddrOrig = (unsigned long)pvCPUVAddr;
+       unsigned long ulAddrRangeOrig = (unsigned long)ui32Bytes;
+       unsigned long ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
+       unsigned long ulStartAddr;
+       unsigned long ulAddrRange;
+       unsigned long ulBeyondEndAddr;
+       unsigned long ulAddr;
+       int iNumPagesMapped;
+       unsigned ui;
+       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) {
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: Couldn't allocate information structure");
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+       memset(psInfo, 0, sizeof(*psInfo));
+
+#if defined(DEBUG)
+       psInfo->ulStartAddr = ulStartAddrOrig;
+       psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+#endif
+
+       psInfo->iNumPages = ulAddrRange >> PAGE_SHIFT;
+       psInfo->iPageOffset = ulStartAddrOrig & ~PAGE_MASK;
+
+       psInfo->psPhysAddr =
+           kmalloc(psInfo->iNumPages * sizeof(*psInfo->psPhysAddr),
+                   GFP_KERNEL);
+       if (psInfo->psPhysAddr == NULL) {
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: Couldn't allocate page array");
+               goto error_free;
+       }
+
+       psInfo->ppsPages =
+           kmalloc(psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
+       if (psInfo->ppsPages == NULL) {
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: 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) {
+                       printk(KERN_WARNING
+                              ": OSCpuVToPageList: Couldn't map all the pages needed (wanted: %d, got %d)",
+                              psInfo->iNumPages, iNumPagesMapped);
+
+                       for (ui = 0; ui < iNumPagesMapped; ui++) {
+                               page_cache_release(psInfo->ppsPages[ui]);
+
+                       }
+                       goto error_free;
+               }
+
+               for (ui = 0; ui < psInfo->iNumPages; ui++) {
+                       IMG_CPU_PHYADDR CPUPhysAddr;
+
+                       CPUPhysAddr.uiAddr =
+                           page_to_pfn(psInfo->ppsPages[ui]) << PAGE_SHIFT;
+                       psInfo->psPhysAddr[ui] =
+                           SysCpuPAddrToSysPAddr(CPUPhysAddr);
+                       psSysPAddr[ui] = psInfo->psPhysAddr[ui];
+
+               }
+
+               psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+               goto exit_check;
+       }
+
+       printk(KERN_WARNING
+              ": OSCpuVToPageList: get_user_pages failed (%d), trying something else",
+              iNumPagesMapped);
+
+       down_read(&current->mm->mmap_sem);
+
+       psVMArea = find_vma(current->mm, ulStartAddrOrig);
+       if (psVMArea == NULL) {
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: 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) {
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: Start address %lx is outside of the region returned by find_vma",
+                      ulStartAddrOrig);
+               goto error_release_mmap_sem;
+       }
+
+       if (ulBeyondEndAddrOrig > psVMArea->vm_end) {
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: 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)) {
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: 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)) {
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: No read/write access to memory region (VMA flags: 0x%lx)",
+                      psVMArea->vm_flags);
+               goto error_release_mmap_sem;
+       }
+
+       for (ulAddr = ulStartAddrOrig, ui = 0; ulAddr < ulBeyondEndAddrOrig;
+            ulAddr += PAGE_SIZE, ui++) {
+               struct page *psPage;
+
+               BUG_ON(ui >= psInfo->iNumPages);
+
+               psPage = CPUVAddrToPage(psVMArea, ulAddr);
+               if (psPage == NULL) {
+                       unsigned uj;
+
+                       printk(KERN_WARNING
+                              ": OSCpuVToPageList: Couldn't lookup page structure for address 0x%lx, trying something else",
+                              ulAddr);
+
+                       for (uj = 0; uj < ui; uj++) {
+                               put_page_testzero(psInfo->ppsPages[uj]);
+                       }
+                       break;
+               }
+
+               psInfo->ppsPages[ui] = psPage;
+       }
+
+       BUG_ON(ui > psInfo->iNumPages);
+       if (ui == psInfo->iNumPages) {
+
+               for (ui = 0; ui < psInfo->iNumPages; ui++) {
+                       struct page *psPage = psInfo->ppsPages[ui];
+                       IMG_CPU_PHYADDR CPUPhysAddr;
+
+                       CPUPhysAddr.uiAddr = page_to_pfn(psPage) << PAGE_SHIFT;
+
+                       psInfo->psPhysAddr[ui] =
+                           SysCpuPAddrToSysPAddr(CPUPhysAddr);
+                       psSysPAddr[ui] = psInfo->psPhysAddr[ui];
+               }
+
+               psInfo->eType = WRAP_TYPE_FIND_VMA_PAGES;
+       } else {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
+
+               if ((psVMArea->vm_flags & VM_PFNMAP) == 0) {
+                       printk(KERN_WARNING
+                              ": OSCpuVToPageList: Region isn't a raw PFN mapping.  Giving up.");
+                       goto error_release_mmap_sem;
+               }
+
+               for (ulAddr = ulStartAddrOrig, ui = 0;
+                    ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, ui++) {
+                       IMG_CPU_PHYADDR CPUPhysAddr;
+
+                       CPUPhysAddr.uiAddr =
+                           ((ulAddr - psVMArea->vm_start) +
+                            (psVMArea->vm_pgoff << PAGE_SHIFT)) & PAGE_MASK;
+
+                       psInfo->psPhysAddr[ui] =
+                           SysCpuPAddrToSysPAddr(CPUPhysAddr);
+                       psSysPAddr[ui] = psInfo->psPhysAddr[ui];
+               }
+               BUG_ON(ui != psInfo->iNumPages);
+
+               psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
+
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: Region can't be locked down");
+#else
+               printk(KERN_WARNING
+                      ": OSCpuVToPageList: 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;
+}
diff --git a/pvr/osfunc.h b/pvr/osfunc.h
new file mode 100644 (file)
index 0000000..f8b91e9
--- /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 
+ *
+ ******************************************************************************/
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG          1
+#endif
+
+#ifndef __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#ifdef __linux__
+#ifdef __KERNEL__
+#include <linux/string.h>
+#endif
+#endif
+
+#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_PAGESIZE()-1)&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_UINT32 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_VOID * pvLinAddr);
+       IMG_VOID OSMemCopy(IMG_VOID * pvDst, IMG_VOID * pvSrc,
+                          IMG_UINT32 ui32Size);
+       IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+                                IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags,
+                                IMG_HANDLE * phOSMemHandle);
+       IMG_BOOL OSUnMapPhysToLin(IMG_VOID * pvLinAddr, IMG_UINT32 ui32Bytes,
+                                 IMG_UINT32 ui32Flags,
+                                 IMG_HANDLE hOSMemHandle);
+
+       PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
+                                  IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags,
+                                  IMG_VOID ** ppvCpuVAddr,
+                                  IMG_HANDLE * phOSMemHandle);
+       PVRSRV_ERROR OSUnReservePhys(IMG_VOID * pvCpuVAddr,
+                                    IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags,
+                                    IMG_HANDLE hOSMemHandle);
+
+#if defined(__linux__)
+       PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR * pBasePAddr,
+                                           IMG_VOID * pvCpuVAddr,
+                                           IMG_UINT32 ui32Bytes,
+                                           IMG_UINT32 ui32Flags,
+                                           IMG_HANDLE * phOSMemHandle);
+       PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID * pvCpuVAddr,
+                                             IMG_UINT32 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_UINT32 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_UINT32
+                                                           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_UINT32 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_UINT32
+                                                           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_UINT32 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_UINT32
+                                                           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_UINT32 ui32Bytes,
+                                  IMG_UINT32 ui32Flags,
+                                  IMG_HANDLE * phOSMemHandle);
+       PVRSRV_ERROR OSUnRegisterMem(IMG_VOID * pvCpuVAddr,
+                                    IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags,
+                                    IMG_HANDLE hOSMemHandle);
+
+#if defined(__linux__)
+       PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+                                      IMG_UINT32 ui32ByteOffset,
+                                      IMG_UINT32 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_UINT32 ui32ByteOffset,
+                                                    IMG_UINT32 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_UINT32 OSGetCurrentThreadID(IMG_VOID);
+       IMG_VOID OSMemSet(IMG_VOID * pvDest, IMG_UINT8 ui8Value,
+                         IMG_UINT32 ui32Size);
+
+#if defined(__linux__) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+       PVRSRV_ERROR _OSAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
+                                IMG_PVOID * ppvLinAddr,
+                                IMG_HANDLE * phBlockAlloc,
+                                IMG_CHAR * pszFilename, IMG_UINT32 ui32Line);
+#define OSAllocMem(ui32Flags, ui32Size, ppvLinAddr, phBlockAlloc) _OSAllocMem(ui32Flags, ui32Size, ppvLinAddr, phBlockAlloc, __FILE__, __LINE__)
+       PVRSRV_ERROR _OSFreeMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
+                               IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc,
+                               IMG_CHAR * pszFilename, IMG_UINT32 ui32Line);
+#define OSFreeMem(ui32Flags, ui32Size, pvLinAddr, phBlockAlloc) _OSFreeMem(ui32Flags, ui32Size, pvLinAddr, phBlockAlloc, __FILE__, __LINE__)
+#else
+       PVRSRV_ERROR OSAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
+                               IMG_PVOID * ppvLinAddr,
+                               IMG_HANDLE * phBlockAlloc);
+       PVRSRV_ERROR OSFreeMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
+                              IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc);
+#endif
+       PVRSRV_ERROR OSAllocPages(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
+                                 IMG_PVOID * ppvLinAddr,
+                                 IMG_HANDLE * phPageAlloc);
+       PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
+                                IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+#if defined(__linux__)
+       IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_VOID * hOSMemHandle,
+                                             IMG_UINT32 ui32ByteOffset);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleToCpuPAddr)
+#endif
+       static INLINE IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_HANDLE
+                                                           hOSMemHandle,
+                                                           IMG_UINT32
+                                                           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_UINT32 ui32Size,
+                            const IMG_CHAR * pszFormat, ...);
+#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_UINT32 ui32Size,
+                                            IMG_CPU_VIRTADDR * pLinAddr,
+                                            IMG_CPU_PHYADDR * pPhysAddr);
+       PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size,
+                                           IMG_CPU_VIRTADDR LinAddr,
+                                           IMG_CPU_PHYADDR PhysAddr);
+
+       IMG_PVOID MapUserFromKernel(IMG_PVOID pvLinAddrKM, IMG_UINT32 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_UINT32 ui32Size,
+                                    IMG_HANDLE hMemBlock);
+
+       PVRSRV_ERROR OSMapPhysToUserSpace(IMG_HANDLE hDevCookie,
+                                         IMG_SYS_PHYADDR sCPUPhysAddr,
+                                         IMG_UINT32 uiSizeInBytes,
+                                         IMG_UINT32 ui32CacheFlags,
+                                         IMG_PVOID * ppvUserAddr,
+                                         IMG_UINT32 * 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 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_UINT32 * pui32Bytes);
+
+       typedef enum _HOST_PCI_INIT_FLAGS_ {
+               HOST_PCI_INIT_FLAG_BUS_MASTER = 0x1,
+               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_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_UINT32 ui32Bytes);
+
+       PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID * pvDest,
+                                 IMG_VOID * pvSrc, IMG_UINT32 ui32Bytes);
+       PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID * pvDest,
+                                   IMG_VOID * pvSrc, IMG_UINT32 ui32Bytes);
+
+#if defined(__linux__)
+       PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID * pvCPUVAddr,
+                                          IMG_UINT32 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_UINT32 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 (__cplusplus)
+}
+#endif
+
+#endif
diff --git a/pvr/pb.c b/pvr/pb.c
new file mode 100644 (file)
index 0000000..f3b5042
--- /dev/null
+++ b/pvr/pb.c
@@ -0,0 +1,469 @@
+/**********************************************************************
+ *
+ * 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 "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+
+#ifndef __linux__
+#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#endif
+
+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 ***
+                     pppsSharedPBDescSubKernelMemInfos,
+                     IMG_UINT32 * ui32SharedPBDescSubKernelMemInfosCount)
+{
+       PVRSRV_STUB_PBDESC *psStubPBDesc;
+       PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = IMG_NULL;
+       PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+       PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+       psSGXDevInfo = ((PVRSRV_DEVICE_NODE *) hDevCookie)->pvDevice;
+
+       psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+       if (psStubPBDesc != IMG_NULL) {
+               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));
+               }
+               {
+                       IMG_UINT32 i;
+                       PRESMAN_ITEM psResItem;
+
+                       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                      sizeof(PVRSRV_KERNEL_MEM_INFO *)
+                                      *
+                                      psStubPBDesc->ui32SubKernelMemInfosCount,
+                                      (IMG_VOID **) &
+                                      ppsSharedPBDescSubKernelMemInfos,
+                                      IMG_NULL) != 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_GENERIC;
+                               goto ExitNotFound;
+                       }
+
+                       *ppsSharedPBDescKernelMemInfo =
+                           psStubPBDesc->psSharedPBDescKernelMemInfo;
+                       *ppsHWPBDescKernelMemInfo =
+                           psStubPBDesc->psHWPBDescKernelMemInfo;
+                       *ppsBlockKernelMemInfo =
+                           psStubPBDesc->psBlockKernelMemInfo;
+
+                       *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_GENERIC;
+                               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)
+{
+       PVRSRV_STUB_PBDESC **ppsStubPBDesc;
+       IMG_UINT32 i;
+       PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+
+       psSGXDevInfo =
+           (PVRSRV_SGXDEV_INFO *) ((PVRSRV_DEVICE_NODE *) psStubPBDescIn->
+                                   hDevCookie)->pvDevice;
+
+       for (ppsStubPBDesc =
+            (PVRSRV_STUB_PBDESC **) & psSGXDevInfo->psStubPBDescListKM;
+            *ppsStubPBDesc != IMG_NULL;
+            ppsStubPBDesc = &(*ppsStubPBDesc)->psNext) {
+               PVRSRV_STUB_PBDESC *psStubPBDesc = *ppsStubPBDesc;
+
+               if (psStubPBDesc == psStubPBDescIn) {
+                       psStubPBDesc->ui32RefCount--;
+                       PVR_ASSERT((IMG_INT32) psStubPBDesc->ui32RefCount >= 0);
+
+                       if (psStubPBDesc->ui32RefCount == 0) {
+                               PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
+                                   (PVRSRV_SGX_HOST_CTL *) psSGXDevInfo->
+                                   psSGXHostCtl;
+#if defined (PDUMP)
+                               IMG_HANDLE hUniqueTag =
+                                   MAKEUNIQUETAG(psSGXDevInfo->
+                                                 psKernelSGXHostCtlMemInfo);
+#endif
+
+                               psSGXHostCtl->sTAHWPBDesc.uiAddr = 0;
+                               psSGXHostCtl->s3DHWPBDesc.uiAddr = 0;
+
+                               PDUMPCOMMENT
+                                   ("TA/3D CCB Control - Reset HW PBDesc records");
+                               PDUMPMEM(IMG_NULL,
+                                        psSGXDevInfo->
+                                        psKernelSGXHostCtlMemInfo,
+                                        offsetof(PVRSRV_SGX_HOST_CTL,
+                                                 sTAHWPBDesc),
+                                        sizeof(IMG_DEV_VIRTADDR),
+                                        PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
+                               PDUMPMEM(IMG_NULL,
+                                        psSGXDevInfo->
+                                        psKernelSGXHostCtlMemInfo,
+                                        offsetof(PVRSRV_SGX_HOST_CTL,
+                                                 s3DHWPBDesc),
+                                        sizeof(IMG_DEV_VIRTADDR),
+                                        PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
+
+                               *ppsStubPBDesc = psStubPBDesc->psNext;
+
+                               for (i = 0;
+                                    i <
+                                    psStubPBDesc->ui32SubKernelMemInfosCount;
+                                    i++) {
+
+                                       PVRSRVFreeDeviceMemKM(psStubPBDesc->
+                                                             hDevCookie,
+                                                             psStubPBDesc->
+                                                             ppsSubKernelMemInfos
+                                                             [i]);
+                               }
+
+                               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                         sizeof(PVRSRV_KERNEL_MEM_INFO *)
+                                         *
+                                         psStubPBDesc->
+                                         ui32SubKernelMemInfosCount,
+                                         psStubPBDesc->ppsSubKernelMemInfos,
+                                         0);
+
+                               PVRSRVFreeSharedSysMemoryKM(psStubPBDesc->
+                                                           psBlockKernelMemInfo);
+
+                               PVRSRVFreeDeviceMemKM(psStubPBDesc->hDevCookie,
+                                                     psStubPBDesc->
+                                                     psHWPBDescKernelMemInfo);
+
+                               PVRSRVFreeSharedSysMemoryKM(psStubPBDesc->
+                                                           psSharedPBDescKernelMemInfo);
+
+                               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                         sizeof(PVRSRV_STUB_PBDESC),
+                                         psStubPBDesc, 0);
+
+                       }
+                       return PVRSRV_OK;
+               }
+       }
+
+       return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+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;
+#else
+       PVR_UNREFERENCED_PARAMETER(pvParam);
+#endif
+
+       PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+       PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
+
+       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,
+                    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_GENERIC;
+       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) != 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) != 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;
+       }
+
+       psStubPBDesc->ui32RefCount = 1;
+       psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
+       psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
+       psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
+       psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
+
+       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;
+
+       psStubPBDesc->psNext = psSGXDevInfo->psStubPBDescListKM;
+       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);
+               }
+               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);
+
+       return eRet;
+}
diff --git a/pvr/pdump.c b/pvr/pdump.c
new file mode 100644 (file)
index 0000000..59c6996
--- /dev/null
@@ -0,0 +1,1397 @@
+/**********************************************************************
+ *
+ * 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 "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 MIN(a,b)       (a > b ? b : a)
+
+#define MAX_FILE_SIZE  0x40000000
+
+static IMG_UINT32 gui32PDumpSuspended = 0;
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+#define PDUMP_STREAM_PARAM2                    0
+#define PDUMP_STREAM_SCRIPT2           1
+#define PDUMP_STREAM_DRIVERINFO                2
+#define PDUMP_NUM_STREAMS                      3
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
+       "ScriptStream2",
+       "DriverInfoStream"
+};
+
+#define __PDBG_PDUMP_STATE_GET_MSG_STRING(ERROR) \
+       IMG_CHAR *pszMsg = gsDBGPdumpState.pszMsg; \
+       if(!pszMsg) return ERROR
+
+#define __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(ERROR) \
+       IMG_CHAR *pszScript = gsDBGPdumpState.pszScript; \
+       if(!pszScript) return ERROR
+
+#define __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(ERROR) \
+       IMG_CHAR *pszScript = gsDBGPdumpState.pszScript; \
+       IMG_CHAR *pszFile = gsDBGPdumpState.pszFile; \
+       if(!pszScript || !pszFile) return ERROR
+
+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
+
+void DBGDrvGetServiceTable(IMG_VOID ** fn_table);
+
+IMG_VOID PDumpInit(IMG_VOID)
+{
+       IMG_UINT32 i = 0;
+
+       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) != PVRSRV_OK) {
+                               goto init_failed;
+                       }
+               }
+
+               if (!gsDBGPdumpState.pszMsg) {
+                       if (OSAllocMem
+                           (PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX,
+                            (IMG_PVOID *) & gsDBGPdumpState.pszMsg,
+                            0) != PVRSRV_OK) {
+                               goto init_failed;
+                       }
+               }
+
+               if (!gsDBGPdumpState.pszScript) {
+                       if (OSAllocMem
+                           (PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX,
+                            (IMG_PVOID *) & gsDBGPdumpState.pszScript,
+                            0) != 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 = 0;
+
+       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;
+}
+
+IMG_VOID PDumpEndInitPhase(IMG_VOID)
+{
+       IMG_UINT32 i;
+
+       PDUMPCOMMENT("End of Init Phase");
+
+       for (i = 0; i < PDUMP_NUM_STREAMS; i++) {
+               gpfnDbgDrv->pfnEndInitPhase(gsDBGPdumpState.psStream[i]);
+       }
+}
+
+void PDumpComment(IMG_CHAR * pszFormat, ...)
+{
+       __PDBG_PDUMP_STATE_GET_MSG_STRING();
+
+       vsnprintf(pszMsg, SZ_MSG_SIZE_MAX, pszFormat,
+                 (IMG_CHAR *) (&pszFormat + 1));
+
+       PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+void PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+{
+       __PDBG_PDUMP_STATE_GET_MSG_STRING();
+
+       vsnprintf(pszMsg, SZ_MSG_SIZE_MAX, pszFormat,
+                 (IMG_CHAR *) (&pszFormat + 1));
+
+       PDumpCommentKM(pszMsg, ui32Flags);
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+       return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.
+                                                psStream
+                                                [PDUMP_STREAM_SCRIPT2]);
+}
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+       return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.
+                                            psStream[PDUMP_STREAM_SCRIPT2],
+                                            IMG_FALSE);
+}
+
+PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_UINT32 ui32Reg, IMG_UINT32 ui32Data,
+                                IMG_UINT32 ui32Flags)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(PVRSRV_ERROR_GENERIC);
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                "WRW :SGXREG:0x%8.8lX 0x%8.8lX\r\n", ui32Reg, ui32Data);
+       PDumpWriteString2(pszScript, ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+void PDumpReg(IMG_UINT32 ui32Reg, IMG_UINT32 ui32Data)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                "WRW :SGXREG:0x%8.8lX 0x%8.8lX\r\n", ui32Reg, ui32Data);
+       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_UINT32 ui32RegAddr,
+                                   IMG_UINT32 ui32RegValue,
+                                   IMG_UINT32 ui32Mask, IMG_UINT32 ui32Flags)
+{
+#define POLL_DELAY                     1000
+#define POLL_COUNT_LONG                (2000000000 / POLL_DELAY)
+#define POLL_COUNT_SHORT       (1000000 / POLL_DELAY)
+
+       IMG_UINT32 ui32PollCount;
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(PVRSRV_ERROR_GENERIC);
+
+       if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+            (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK))
+           || ((ui32RegAddr == EUR_CR_EVENT_STATUS)
+               && (ui32RegValue & ui32Mask &
+                   EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK))
+           || ((ui32RegAddr == EUR_CR_EVENT_STATUS)
+               && (ui32RegValue & ui32Mask &
+                   EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK))) {
+               ui32PollCount = POLL_COUNT_LONG;
+       } else {
+               ui32PollCount = POLL_COUNT_SHORT;
+       }
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                "POL :SGXREG:0x%8.8lX 0x%8.8lX 0x%8.8lX %d %lu %d\r\n",
+                ui32RegAddr, ui32RegValue, ui32Mask, 0, ui32PollCount,
+                POLL_DELAY);
+       PDumpWriteString2(pszScript, ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegPolKM(IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue,
+                          IMG_UINT32 ui32Mask)
+{
+       return PDumpRegPolWithFlagsKM(ui32RegAddr, ui32RegValue, ui32Mask,
+                                     PDUMP_FLAGS_CONTINUOUS);
+}
+
+IMG_VOID PDumpMallocPages(PVRSRV_DEVICE_TYPE eDeviceType,
+                         IMG_UINT32 ui32DevVAddr,
+                         IMG_CPU_VIRTADDR pvLinAddr,
+                         IMG_HANDLE hOSMemHandle,
+                         IMG_UINT32 ui32NumBytes, IMG_HANDLE hUniqueTag)
+{
+       IMG_UINT32 ui32Offset;
+       IMG_UINT32 ui32NumPages;
+       IMG_CPU_PHYADDR sCpuPAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_UINT32 ui32Page;
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+       PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+
+       PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+       PVR_ASSERT(hOSMemHandle);
+       PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                "-- MALLOC :SGXMEM:VA_%8.8lX 0x%8.8lX %lu\r\n", ui32DevVAddr,
+                ui32NumBytes, SGX_MMU_PAGE_SIZE);
+       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+       ui32Offset = 0;
+       ui32NumPages = ui32NumBytes >> SGX_MMU_PAGE_SHIFT;
+       while (ui32NumPages--) {
+               sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+               PVR_ASSERT((sCpuPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+               ui32Offset += SGX_MMU_PAGE_SIZE;
+               sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+               ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+
+               snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                        "MALLOC :SGXMEM:PA_%p%8.8lX %lu %lu 0x%8.8lX\r\n",
+                        hUniqueTag, ui32Page * SGX_MMU_PAGE_SIZE,
+                        SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE,
+                        ui32Page * SGX_MMU_PAGE_SIZE);
+               PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+       }
+}
+
+IMG_VOID PDumpMallocPageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+                             IMG_CPU_VIRTADDR pvLinAddr,
+                             IMG_UINT32 ui32NumBytes, IMG_HANDLE hUniqueTag)
+{
+       IMG_PUINT8 pui8LinAddr;
+       IMG_UINT32 ui32NumPages;
+       IMG_CPU_PHYADDR sCpuPAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_UINT32 ui32Page;
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       PVR_ASSERT(((IMG_UINT32) pvLinAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+       PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                "-- MALLOC :SGXMEM:PAGE_TABLE 0x%8.8lX %lu\r\n", ui32NumBytes,
+                SGX_MMU_PAGE_SIZE);
+       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+       pui8LinAddr = (IMG_PUINT8) pvLinAddr;
+       ui32NumPages = ui32NumBytes >> SGX_MMU_PAGE_SHIFT;
+       while (ui32NumPages--) {
+               sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+               sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+               ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+               pui8LinAddr += SGX_MMU_PAGE_SIZE;
+
+               snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                        "MALLOC :SGXMEM:PA_%p%8.8lX 0x%lX %lu 0x%8.8lX\r\n",
+                        hUniqueTag, ui32Page * SGX_MMU_PAGE_SIZE,
+                        SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE,
+                        ui32Page * SGX_MMU_PAGE_SIZE);
+               PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+       }
+}
+
+IMG_VOID PDumpFreePages(BM_HEAP * psBMHeap,
+                       IMG_DEV_VIRTADDR sDevVAddr,
+                       IMG_UINT32 ui32NumBytes,
+                       IMG_HANDLE hUniqueTag, IMG_BOOL bInterleaved)
+{
+       IMG_UINT32 ui32NumPages, ui32PageCounter;
+       IMG_DEV_PHYADDR sDevPAddr;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       PVR_ASSERT(((IMG_UINT32) sDevVAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1)) ==
+                  0);
+       PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "-- FREE :SGXMEM:VA_%8.8lX\r\n",
+                sDevVAddr.uiAddr);
+       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+       ui32NumPages = ui32NumBytes >> SGX_MMU_PAGE_SHIFT;
+       psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+       for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages;
+            ui32PageCounter++) {
+               if (!bInterleaved || (ui32PageCounter % 2) == 0) {
+                       sDevPAddr =
+                           psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->
+                                                               pMMUHeap,
+                                                               sDevVAddr);
+
+                       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                                "FREE :SGXMEM:PA_%p%8.8lX\r\n", hUniqueTag,
+                                sDevPAddr.uiAddr);
+                       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+               } else {
+
+               }
+
+               sDevVAddr.uiAddr += SGX_MMU_PAGE_SIZE;
+       }
+}
+
+IMG_VOID PDumpFreePageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+                           IMG_CPU_VIRTADDR pvLinAddr,
+                           IMG_UINT32 ui32NumBytes, IMG_HANDLE hUniqueTag)
+{
+       IMG_PUINT8 pui8LinAddr;
+       IMG_UINT32 ui32NumPages;
+       IMG_CPU_PHYADDR sCpuPAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_UINT32 ui32Page;
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       PVR_ASSERT(((IMG_UINT32) pvLinAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+       PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                "-- FREE :SGXMEM:PAGE_TABLE\r\n");
+       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+       pui8LinAddr = (IMG_PUINT8) pvLinAddr;
+       ui32NumPages = ui32NumBytes >> SGX_MMU_PAGE_SHIFT;
+       while (ui32NumPages--) {
+               sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+               sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+               ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+               pui8LinAddr += SGX_MMU_PAGE_SIZE;
+
+               snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                        "FREE :SGXMEM:PA_%p%8.8lX\r\n", hUniqueTag,
+                        ui32Page * SGX_MMU_PAGE_SIZE);
+               PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+       }
+}
+
+IMG_VOID PDumpPDReg(IMG_UINT32 ui32Reg,
+                   IMG_UINT32 ui32Data, IMG_HANDLE hUniqueTag)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       snprintf(pszScript,
+                SZ_SCRIPT_SIZE_MAX,
+                "WRW :SGXREG:0x%8.8lX :SGXMEM:PA_%p%8.8lX:0x%8.8lX\r\n",
+                ui32Reg,
+                hUniqueTag,
+                ui32Data & ~(SGX_MMU_PAGE_SIZE - 1),
+                ui32Data & (SGX_MMU_PAGE_SIZE - 1));
+       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+}
+
+IMG_VOID PDumpPDRegWithFlags(IMG_UINT32 ui32Reg,
+                            IMG_UINT32 ui32Data,
+                            IMG_UINT32 ui32Flags, IMG_HANDLE hUniqueTag)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       snprintf(pszScript,
+                SZ_SCRIPT_SIZE_MAX,
+                "WRW :SGXREG:0x%8.8lX :SGXMEM:PA_%p%8.8lX:0x%8.8lX\r\n",
+                ui32Reg,
+                hUniqueTag,
+                ui32Data & ~(SGX_MMU_PAGE_SIZE - 1),
+                ui32Data & (SGX_MMU_PAGE_SIZE - 1));
+       PDumpWriteString2(pszScript, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO * psMemInfo,
+                          IMG_UINT32 ui32Offset,
+                          IMG_UINT32 ui32Value,
+                          IMG_UINT32 ui32Mask,
+                          PDUMP_POLL_OPERATOR eOperator,
+                          IMG_BOOL bLastFrame,
+                          IMG_BOOL bOverwrite, IMG_HANDLE hUniqueTag)
+{
+#define MEMPOLL_DELAY          (1000)
+#define MEMPOLL_COUNT          (2000000000 / MEMPOLL_DELAY)
+
+       IMG_UINT32 ui32PageOffset;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_DEV_VIRTADDR sDevVPageAddr;
+       IMG_CPU_PHYADDR CpuPAddr;
+       IMG_UINT32 ui32Flags;
+       __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC);
+
+       PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <=
+                  psMemInfo->ui32AllocSize);
+
+       if (gsDBGPdumpState.ui32ParamFileNum == 0) {
+               snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm");
+       } else {
+               snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%lu.prm",
+                        gsDBGPdumpState.ui32ParamFileNum);
+       }
+
+       ui32Flags = 0;
+
+       if (bLastFrame) {
+               ui32Flags |= PDUMP_FLAGS_LASTFRAME;
+       }
+
+       if (bOverwrite) {
+               ui32Flags |= PDUMP_FLAGS_RESETLFBUFFER;
+       }
+
+       CpuPAddr =
+           OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
+       ui32PageOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
+
+       sDevVPageAddr.uiAddr =
+           psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+       BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+       sDevPAddr.uiAddr += ui32PageOffset;
+
+       snprintf(pszScript,
+                SZ_SCRIPT_SIZE_MAX,
+                "POL :SGXMEM:PA_%p%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %d %d %d\r\n",
+                hUniqueTag,
+                sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+                sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+                ui32Value, ui32Mask, eOperator, MEMPOLL_COUNT, MEMPOLL_DELAY);
+       PDumpWriteString2(pszScript, 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)
+{
+       IMG_UINT32 ui32PageByteOffset;
+       IMG_UINT8 *pui8DataLinAddr;
+       IMG_DEV_VIRTADDR sDevVPageAddr;
+       IMG_DEV_VIRTADDR sDevVAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_CPU_PHYADDR CpuPAddr;
+       IMG_UINT32 ui32ParamOutPos;
+       IMG_UINT32 ui32CurrentOffset;
+       IMG_UINT32 ui32BytesRemaining;
+       LinuxMemArea *psLinuxMemArea;
+       LINUX_MEM_AREA_TYPE eRootAreaType;
+       IMG_CHAR *pui8TransientCpuVAddr;
+
+       __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC);
+
+       PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize);
+
+       if (ui32Bytes == 0 || gui32PDumpSuspended) {
+               return PVRSRV_OK;
+       }
+
+       if (pvAltLinAddr) {
+               pui8DataLinAddr = pvAltLinAddr;
+       } else if (psMemInfo->pvLinAddrKM) {
+               pui8DataLinAddr =
+                   (IMG_UINT8 *) psMemInfo->pvLinAddrKM + ui32Offset;
+       } else {
+               pui8DataLinAddr = 0;
+               psLinuxMemArea =
+                   (LinuxMemArea *) psMemInfo->sMemBlk.hOSMemHandle;
+               eRootAreaType = LinuxMemAreaRootType(psLinuxMemArea);
+       }
+
+       ui32ParamOutPos =
+           gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.
+                                          psStream[PDUMP_STREAM_PARAM2]);
+
+       if (pui8DataLinAddr) {
+               if (!PDumpWriteILock
+                   (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2],
+                    pui8DataLinAddr, ui32Bytes, ui32Flags)) {
+                       return PVRSRV_ERROR_GENERIC;
+               }
+       }
+
+       else if (eRootAreaType == LINUX_MEM_AREA_IO) {
+
+               CpuPAddr =
+                   OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle,
+                                         ui32Offset);
+               pui8TransientCpuVAddr =
+                   IORemapWrapper(CpuPAddr, ui32Bytes, PVRSRV_HAP_CACHED);
+               if (!PDumpWriteILock
+                   (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2],
+                    pui8TransientCpuVAddr, ui32Bytes, ui32Flags)) {
+                       IOUnmapWrapper(pui8TransientCpuVAddr);
+                       return PVRSRV_ERROR_GENERIC;
+               }
+               IOUnmapWrapper(pui8TransientCpuVAddr);
+       } else {
+
+               PVR_ASSERT(eRootAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+               ui32BytesRemaining = ui32Bytes;
+               ui32CurrentOffset = ui32Offset;
+
+               while (ui32BytesRemaining > 0) {
+                       IMG_UINT32 ui32BlockBytes =
+                           MIN(ui32BytesRemaining, PAGE_SIZE);
+                       struct page *psCurrentPage = NULL;
+
+                       CpuPAddr =
+                           OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.
+                                                 hOSMemHandle,
+                                                 ui32CurrentOffset);
+
+                       if (CpuPAddr.uiAddr & (PAGE_SIZE - 1)) {
+                               ui32BlockBytes =
+                                   MIN(ui32BytesRemaining,
+                                       PAGE_ALIGN(CpuPAddr.uiAddr) -
+                                       CpuPAddr.uiAddr);
+                       }
+
+                       psCurrentPage =
+                           LinuxMemAreaOffsetToPage(psLinuxMemArea,
+                                                    ui32CurrentOffset);
+                       pui8TransientCpuVAddr = KMapWrapper(psCurrentPage);
+                       pui8TransientCpuVAddr += (CpuPAddr.uiAddr & ~PAGE_MASK);
+                       if (!pui8TransientCpuVAddr) {
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+
+                       if (!PDumpWriteILock
+                           (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2],
+                            pui8TransientCpuVAddr, ui32BlockBytes,
+                            ui32Flags)) {
+                               KUnMapWrapper(psCurrentPage);
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+
+                       KUnMapWrapper(psCurrentPage);
+
+                       ui32BytesRemaining -= ui32BlockBytes;
+                       ui32CurrentOffset += ui32BlockBytes;
+               }
+               PVR_ASSERT(ui32BytesRemaining == 0);
+
+       }
+
+       if (gsDBGPdumpState.ui32ParamFileNum == 0) {
+               snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm");
+       } else {
+               snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%lu.prm",
+                        gsDBGPdumpState.ui32ParamFileNum);
+       }
+
+       snprintf(pszScript,
+                SZ_SCRIPT_SIZE_MAX,
+                "-- LDB :SGXMEM:VA_%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+                psMemInfo->sDevVAddr.uiAddr,
+                ui32Offset, ui32Bytes, ui32ParamOutPos, pszFile);
+       PDumpWriteString2(pszScript, ui32Flags);
+
+       CpuPAddr =
+           OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
+       ui32PageByteOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
+
+       sDevVAddr = psMemInfo->sDevVAddr;
+       sDevVAddr.uiAddr += ui32Offset;
+
+       ui32BytesRemaining = ui32Bytes;
+       ui32CurrentOffset = ui32Offset;
+
+       while (ui32BytesRemaining > 0) {
+               IMG_UINT32 ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_SIZE);
+               CpuPAddr =
+                   OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle,
+                                         ui32CurrentOffset);
+
+               sDevVPageAddr.uiAddr =
+                   psMemInfo->sDevVAddr.uiAddr + ui32CurrentOffset -
+                   ui32PageByteOffset;
+
+               BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+               sDevPAddr.uiAddr += ui32PageByteOffset;
+
+               if (ui32PageByteOffset) {
+                       ui32BlockBytes =
+                           MIN(ui32BytesRemaining,
+                               PAGE_ALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr);
+
+                       ui32PageByteOffset = 0;
+               }
+
+               snprintf(pszScript,
+                        SZ_SCRIPT_SIZE_MAX,
+                        "LDB :SGXMEM:PA_%p%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+                        hUniqueTag,
+                        sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+                        sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+                        ui32BlockBytes, ui32ParamOutPos, pszFile);
+               PDumpWriteString2(pszScript, ui32Flags);
+
+               ui32BytesRemaining -= ui32BlockBytes;
+               ui32CurrentOffset += ui32BlockBytes;
+               ui32ParamOutPos += ui32BlockBytes;
+       }
+       PVR_ASSERT(ui32BytesRemaining == 0);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMem2KM(PVRSRV_DEVICE_TYPE eDeviceType,
+                        IMG_CPU_VIRTADDR pvLinAddr,
+                        IMG_UINT32 ui32Bytes,
+                        IMG_UINT32 ui32Flags,
+                        IMG_BOOL bInitialisePages,
+                        IMG_HANDLE hUniqueTag1, IMG_HANDLE hUniqueTag2)
+{
+       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;
+
+       __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC);
+
+       if (ui32Flags) ;
+
+       if (!pvLinAddr) {
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       if (gui32PDumpSuspended) {
+               return PVRSRV_OK;
+       }
+
+       ui32ParamOutPos =
+           gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.
+                                          psStream[PDUMP_STREAM_PARAM2]);
+
+       if (bInitialisePages) {
+
+               if (!PDumpWriteILock
+                   (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], pvLinAddr,
+                    ui32Bytes, PDUMP_FLAGS_CONTINUOUS)) {
+                       return PVRSRV_ERROR_GENERIC;
+               }
+
+               if (gsDBGPdumpState.ui32ParamFileNum == 0) {
+                       snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm");
+               } else {
+                       snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%lu.prm",
+                                gsDBGPdumpState.ui32ParamFileNum);
+               }
+       }
+
+       ui32PageOffset = (IMG_UINT32) pvLinAddr & (HOST_PAGESIZE() - 1);
+       ui32NumPages =
+           (ui32PageOffset + ui32Bytes + HOST_PAGESIZE() -
+            1) / HOST_PAGESIZE();
+       pui8LinAddr = (IMG_UINT8 *) pvLinAddr;
+
+       while (ui32NumPages--) {
+               sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+               sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+               if (ui32PageOffset + ui32Bytes > HOST_PAGESIZE()) {
+
+                       ui32BlockBytes = HOST_PAGESIZE() - ui32PageOffset;
+               } else {
+
+                       ui32BlockBytes = ui32Bytes;
+               }
+
+               if (bInitialisePages) {
+                       snprintf(pszScript,
+                                SZ_SCRIPT_SIZE_MAX,
+                                "LDB :SGXMEM:PA_%p%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+                                hUniqueTag1,
+                                sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+                                sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+                                ui32BlockBytes, ui32ParamOutPos, pszFile);
+                       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+               } else {
+                       for (ui32Offset = 0; ui32Offset < ui32BlockBytes;
+                            ui32Offset += sizeof(IMG_UINT32)) {
+                               IMG_UINT32 ui32PTE =
+                                   *((IMG_UINT32 *) (pui8LinAddr +
+                                                     ui32Offset));
+
+                               if ((ui32PTE & SGX_MMU_PDE_ADDR_MASK) != 0) {
+                                       snprintf(pszScript,
+                                                SZ_SCRIPT_SIZE_MAX,
+                                                "WRW :SGXMEM:PA_%p%8.8lX:0x%8.8lX :SGXMEM:PA_%p%8.8lX:0x%8.8lX\r\n",
+                                                hUniqueTag1,
+                                                (sDevPAddr.uiAddr +
+                                                 ui32Offset) &
+                                                ~(SGX_MMU_PAGE_SIZE - 1),
+                                                (sDevPAddr.uiAddr +
+                                                 ui32Offset) &
+                                                (SGX_MMU_PAGE_SIZE - 1),
+                                                hUniqueTag2,
+                                                ui32PTE &
+                                                SGX_MMU_PDE_ADDR_MASK,
+                                                ui32PTE &
+                                                ~SGX_MMU_PDE_ADDR_MASK);
+                               } else {
+                                       PVR_ASSERT(!
+                                                  (ui32PTE &
+                                                   SGX_MMU_PTE_VALID));
+                                       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                                                "WRW :SGXMEM:PA_%p%8.8lX:0x%8.8lX 0x%8.8lX%p\r\n",
+                                                hUniqueTag1,
+                                                (sDevPAddr.uiAddr +
+                                                 ui32Offset) &
+                                                ~(SGX_MMU_PAGE_SIZE - 1),
+                                                (sDevPAddr.uiAddr +
+                                                 ui32Offset) &
+                                                (SGX_MMU_PAGE_SIZE - 1),
+                                                ui32PTE, hUniqueTag2);
+                               }
+                               PDumpWriteString2(pszScript,
+                                                 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)
+{
+       IMG_UINT32 ui32ParamOutPos;
+       IMG_CPU_PHYADDR CpuPAddr;
+       IMG_UINT32 ui32PageByteOffset;
+       IMG_DEV_VIRTADDR sDevVAddr;
+       IMG_DEV_VIRTADDR sDevVPageAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+
+       __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC);
+
+       ui32ParamOutPos =
+           gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.
+                                          psStream[PDUMP_STREAM_PARAM2]);
+
+       if (!PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2],
+                            (IMG_UINT8 *) & sPDDevPAddr,
+                            sizeof(IMG_DEV_PHYADDR), PDUMP_FLAGS_CONTINUOUS)) {
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       if (gsDBGPdumpState.ui32ParamFileNum == 0) {
+               snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm");
+       } else {
+               snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%lu.prm",
+                        gsDBGPdumpState.ui32ParamFileNum);
+       }
+
+       CpuPAddr =
+           OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
+       ui32PageByteOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
+
+       sDevVAddr = psMemInfo->sDevVAddr;
+       sDevVAddr.uiAddr += ui32Offset;
+
+       sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+       BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+       sDevPAddr.uiAddr += ui32PageByteOffset;
+
+       if ((sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK) != 0) {
+               snprintf(pszScript,
+                        SZ_SCRIPT_SIZE_MAX,
+                        "WRW :SGXMEM:PA_%p%8.8lX:0x%8.8lX :SGXMEM:PA_%p%8.8lX:0x%8.8lX\r\n",
+                        hUniqueTag1,
+                        sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+                        sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+                        hUniqueTag2,
+                        sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK,
+                        sPDDevPAddr.uiAddr & ~SGX_MMU_PDE_ADDR_MASK);
+       } else {
+               PVR_ASSERT(!(sDevPAddr.uiAddr & SGX_MMU_PTE_VALID));
+               snprintf(pszScript,
+                        SZ_SCRIPT_SIZE_MAX,
+                        "WRW :SGXMEM:PA_%p%8.8lX:0x%8.8lX 0x%8.8lX\r\n",
+                        hUniqueTag1,
+                        sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+                        sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+                        sPDDevPAddr.uiAddr);
+       }
+       PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+       return PVRSRV_OK;
+}
+
+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;
+}
+
+PVRSRV_ERROR PDumpCommentKM(IMG_CHAR * pszComment, IMG_UINT32 ui32Flags)
+{
+       IMG_UINT32 ui32Count = 0;
+       PVRSRV_ERROR eError;
+       __PDBG_PDUMP_STATE_GET_MSG_STRING(PVRSRV_ERROR_GENERIC);
+
+       if (ui32Flags & PDUMP_FLAGS_CONTINUOUS) {
+               eError = PVRSRV_ERROR_GENERIC;
+       } else {
+               eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+       }
+
+       if (!PDumpWriteString2("-- ", ui32Flags)) {
+               return eError;
+       }
+
+       snprintf(pszMsg, SZ_MSG_SIZE_MAX, "%s", pszComment);
+
+       while ((pszMsg[ui32Count] != 0) && (ui32Count < SZ_MSG_SIZE_MAX)) {
+               ui32Count++;
+       }
+
+       if ((pszMsg[ui32Count - 1] != '\n') && (ui32Count < SZ_MSG_SIZE_MAX)) {
+               pszMsg[ui32Count] = '\n';
+               ui32Count++;
+               pszMsg[ui32Count] = '\0';
+       }
+       if ((pszMsg[ui32Count - 2] != '\r') && (ui32Count < SZ_MSG_SIZE_MAX)) {
+               pszMsg[ui32Count - 1] = '\r';
+               pszMsg[ui32Count] = '\n';
+               ui32Count++;
+               pszMsg[ui32Count] = '\0';
+       }
+
+       PDumpWriteString2(pszMsg, ui32Flags);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+       IMG_UINT32 ui32Count = 0;
+       __PDBG_PDUMP_STATE_GET_MSG_STRING(PVRSRV_ERROR_GENERIC);
+
+       snprintf(pszMsg, SZ_MSG_SIZE_MAX, "%s", pszString);
+
+       while ((pszMsg[ui32Count] != 0) && (ui32Count < SZ_MSG_SIZE_MAX)) {
+               ui32Count++;
+       }
+
+       if ((pszMsg[ui32Count - 1] != '\n') && (ui32Count < SZ_MSG_SIZE_MAX)) {
+               pszMsg[ui32Count] = '\n';
+               ui32Count++;
+               pszMsg[ui32Count] = '\0';
+       }
+       if ((pszMsg[ui32Count - 2] != '\r') && (ui32Count < SZ_MSG_SIZE_MAX)) {
+               pszMsg[ui32Count - 1] = '\r';
+               pszMsg[ui32Count] = '\n';
+               ui32Count++;
+               pszMsg[ui32Count] = '\0';
+       }
+
+       if (!PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_DRIVERINFO],
+                            (IMG_UINT8 *) pszMsg, ui32Count, ui32Flags)) {
+               if (ui32Flags & PDUMP_FLAGS_CONTINUOUS) {
+                       return PVRSRV_ERROR_GENERIC;
+               } else {
+                       return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpBitmapKM(IMG_CHAR * pszFileName,
+                          IMG_UINT32 ui32FileOffset,
+                          IMG_UINT32 ui32Width,
+                          IMG_UINT32 ui32Height,
+                          IMG_UINT32 ui32StrideInBytes,
+                          IMG_DEV_VIRTADDR sDevBaseAddr,
+                          IMG_UINT32 ui32Size,
+                          PDUMP_PIXEL_FORMAT ePixelFormat,
+                          PDUMP_MEM_FORMAT eMemFormat,
+                          IMG_UINT32 ui32PDumpFlags)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(PVRSRV_ERROR_GENERIC);
+       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+                             "\r\n-- Dump bitmap of render\r\n");
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+       snprintf(pszScript,
+                SZ_SCRIPT_SIZE_MAX,
+                "SII %s %s.bin :SGXMEM:v%x:0x%08lX 0x%08lX 0x%08lX 0x%08X 0x%08lX 0x%08lX 0x%08lX 0x%08X\r\n",
+                pszFileName,
+                pszFileName,
+                PDUMP_DATAMASTER_PIXEL,
+                sDevBaseAddr.uiAddr,
+                ui32Size,
+                ui32FileOffset,
+                ePixelFormat,
+                ui32Width, ui32Height, ui32StrideInBytes, eMemFormat);
+#else
+       snprintf(pszScript,
+                SZ_SCRIPT_SIZE_MAX,
+                "SII %s %s.bin :SGXMEM:v:0x%08lX 0x%08lX 0x%08lX 0x%08X 0x%08lX 0x%08lX 0x%08lX 0x%08X\r\n",
+                pszFileName,
+                pszFileName,
+                sDevBaseAddr.uiAddr,
+                ui32Size,
+                ui32FileOffset,
+                ePixelFormat,
+                ui32Width, ui32Height, ui32StrideInBytes, eMemFormat);
+#endif
+
+       PDumpWriteString2(pszScript, ui32PDumpFlags);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR * pszFileName,
+                           IMG_UINT32 ui32FileOffset,
+                           IMG_UINT32 ui32Address,
+                           IMG_UINT32 ui32Size, IMG_UINT32 ui32PDumpFlags)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(PVRSRV_ERROR_GENERIC);
+
+       snprintf(pszScript,
+                SZ_SCRIPT_SIZE_MAX,
+                "SAB :SGXREG:0x%08lX 0x%08lX %s\r\n",
+                ui32Address, ui32FileOffset, pszFileName);
+
+       PDumpWriteString2(pszScript, ui32PDumpFlags);
+
+       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 || gui32PDumpSuspended || (ui32Flags & PDUMP_FLAGS_NEVER)) {
+               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) {
+
+               if ((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) &&
+                   (psStream->ui32Start == 0xFFFFFFFF) &&
+                   (psStream->ui32End == 0xFFFFFFFF) &&
+                   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_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
+{
+       IMG_BOOL bFrameDumped;
+
+       bFrameDumped = IMG_FALSE;
+       PDumpSetFrameKM(ui32CurrentFrame + 1);
+       bFrameDumped = PDumpIsCaptureFrameKM();
+       PDumpSetFrameKM(ui32CurrentFrame);
+
+       return bFrameDumped;
+}
+
+IMG_VOID PDump3DSignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+                                  IMG_BOOL bLastFrame,
+                                  IMG_UINT32 * pui32Registers,
+                                  IMG_UINT32 ui32NumRegisters)
+{
+       IMG_UINT32 ui32FileOffset, ui32Flags;
+       IMG_UINT32 i;
+
+       __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING();
+
+       ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+       ui32FileOffset = 0;
+
+       PDUMPCOMMENTWITHFLAGS(ui32Flags,
+                             "\r\n-- Dump 3D signature registers\r\n");
+       snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "out%lu_3d.sig",
+                ui32DumpFrameNum);
+
+       for (i = 0; i < ui32NumRegisters; i++) {
+               PDumpReadRegKM(pszFile, ui32FileOffset, pui32Registers[i],
+                              sizeof(IMG_UINT32), ui32Flags);
+               ui32FileOffset += sizeof(IMG_UINT32);
+       }
+}
+
+static IMG_VOID PDumpCountRead(IMG_CHAR * pszFileName,
+                              IMG_UINT32 ui32Address,
+                              IMG_UINT32 ui32Size,
+                              IMG_UINT32 * pui32FileOffset,
+                              IMG_BOOL bLastFrame)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+                "SAB :SGXREG:0x%08lX 0x%08lX %s\r\n", ui32Address,
+                *pui32FileOffset, pszFileName);
+       PDumpWriteString2(pszScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+
+       *pui32FileOffset += ui32Size;
+}
+
+IMG_VOID PDumpCounterRegisters(IMG_UINT32 ui32DumpFrameNum,
+                              IMG_BOOL bLastFrame,
+                              IMG_UINT32 * pui32Registers,
+                              IMG_UINT32 ui32NumRegisters)
+{
+       IMG_UINT32 ui32FileOffset;
+       IMG_UINT32 i;
+
+       __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING();
+
+       PDUMPCOMMENTWITHFLAGS(bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0,
+                             "\r\n-- Dump counter registers\r\n");
+       snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "out%lu.perf",
+                ui32DumpFrameNum);
+       ui32FileOffset = 0;
+
+       for (i = 0; i < ui32NumRegisters; i++) {
+               PDumpCountRead(pszFile, pui32Registers[i], sizeof(IMG_UINT32),
+                              &ui32FileOffset, bLastFrame);
+       }
+}
+
+IMG_VOID PDumpTASignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+                                  IMG_UINT32 ui32TAKickCount,
+                                  IMG_BOOL bLastFrame,
+                                  IMG_UINT32 * pui32Registers,
+                                  IMG_UINT32 ui32NumRegisters)
+{
+       IMG_UINT32 ui32FileOffset, ui32Flags;
+       IMG_UINT32 i;
+
+       __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING();
+
+       ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+       PDUMPCOMMENTWITHFLAGS(ui32Flags,
+                             "\r\n-- Dump TA signature registers\r\n");
+       snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "out%lu_ta.sig",
+                ui32DumpFrameNum);
+
+       ui32FileOffset =
+           ui32TAKickCount * ui32NumRegisters * sizeof(IMG_UINT32);
+
+       for (i = 0; i < ui32NumRegisters; i++) {
+               PDumpReadRegKM(pszFile, ui32FileOffset, pui32Registers[i],
+                              sizeof(IMG_UINT32), ui32Flags);
+               ui32FileOffset += sizeof(IMG_UINT32);
+       }
+}
+
+IMG_VOID PDumpRegRead(const IMG_UINT32 ui32RegOffset, IMG_UINT32 ui32Flags)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "RDW :SGXREG:0x%lX\r\n",
+                ui32RegOffset);
+       PDumpWriteString2(pszScript, ui32Flags);
+}
+
+IMG_VOID PDumpCycleCountRegRead(const IMG_UINT32 ui32RegOffset,
+                               IMG_BOOL bLastFrame)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "RDW :SGXREG:0x%lX\r\n",
+                ui32RegOffset);
+       PDumpWriteString2(pszScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+}
+
+void PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+             IMG_UINT32 ui32ROffOffset,
+             IMG_UINT32 ui32WPosVal,
+             IMG_UINT32 ui32PacketSize,
+             IMG_UINT32 ui32BufferSize,
+             IMG_UINT32 ui32Flags, IMG_HANDLE hUniqueTag)
+{
+       IMG_UINT32 ui32PageOffset;
+       IMG_DEV_VIRTADDR sDevVAddr;
+       IMG_DEV_PHYADDR sDevPAddr;
+       IMG_DEV_VIRTADDR sDevVPageAddr;
+       IMG_CPU_PHYADDR CpuPAddr;
+
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <=
+                  psROffMemInfo->ui32AllocSize);
+
+       sDevVAddr = psROffMemInfo->sDevVAddr;
+
+       sDevVAddr.uiAddr += ui32ROffOffset;
+
+       CpuPAddr =
+           OSMemHandleToCpuPAddr(psROffMemInfo->sMemBlk.hOSMemHandle,
+                                 ui32ROffOffset);
+       ui32PageOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
+
+       sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+       BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+       sDevPAddr.uiAddr += ui32PageOffset;
+
+       snprintf(pszScript,
+                SZ_SCRIPT_SIZE_MAX,
+                "CBP :SGXMEM:PA_%p%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX 0x%8.8lX\r\n",
+                hUniqueTag,
+                sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+                sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+                ui32WPosVal, ui32PacketSize, ui32BufferSize);
+       PDumpWriteString2(pszScript, ui32Flags);
+}
+
+IMG_VOID PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+{
+       __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+       sprintf(pszScript, "IDL %lu\r\n", ui32Clocks);
+       PDumpWriteString2(pszScript, ui32Flags);
+}
+
+IMG_VOID PDumpIDL(IMG_UINT32 ui32Clocks)
+{
+       PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+       gui32PDumpSuspended++;
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+       gui32PDumpSuspended--;
+}
+
+#endif
diff --git a/pvr/pdump_km.h b/pvr/pdump_km.h
new file mode 100644 (file)
index 0000000..988f105
--- /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 _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define PDUMP_FLAGS_NEVER                      0x08000000
+#define PDUMP_FLAGS_TOOUT2MEM          0x10000000
+#define PDUMP_FLAGS_LASTFRAME          0x20000000
+#define PDUMP_FLAGS_RESETLFBUFFER      0x40000000
+#define PDUMP_FLAGS_CONTINUOUS         0x80000000
+
+#define PDUMP_PD_UNIQUETAG                     (IMG_HANDLE)0
+#define PDUMP_PT_UNIQUETAG                     (IMG_HANDLE)0
+
+#ifndef PDUMP
+#define MAKEUNIQUETAG(hMemInfo)        (0)
+#endif
+
+#ifdef PDUMP
+
+#define MAKEUNIQUETAG(hMemInfo)        (((BM_BUF *)(((PVRSRV_KERNEL_MEM_INFO *)hMemInfo)->sMemBlk.hBuffer))->pMapping)
+
+#define PDUMP_REG_FUNC_NAME PDumpReg
+
+       IMG_IMPORT PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *
+                                             psMemInfo, IMG_UINT32 ui32Offset,
+                                             IMG_UINT32 ui32Value,
+                                             IMG_UINT32 ui32Mask,
+                                             PDUMP_POLL_OPERATOR eOperator,
+                                             IMG_BOOL bLastFrame,
+                                             IMG_BOOL bOverwrite,
+                                             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 PDumpMem2KM(PVRSRV_DEVICE_TYPE eDeviceType,
+                                IMG_CPU_VIRTADDR pvLinAddr,
+                                IMG_UINT32 ui32Bytes,
+                                IMG_UINT32 ui32Flags,
+                                IMG_BOOL bInitialisePages,
+                                IMG_HANDLE hUniqueTag1,
+                                IMG_HANDLE hUniqueTag2);
+       IMG_VOID PDumpInit(IMG_VOID);
+       IMG_VOID PDumpDeInit(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_UINT32 ui32RegAddr,
+                                        IMG_UINT32 ui32RegValue,
+                                        IMG_UINT32 ui32Flags);
+       IMG_IMPORT PVRSRV_ERROR PDumpBitmapKM(IMG_CHAR * pszFileName,
+                                             IMG_UINT32 ui32FileOffset,
+                                             IMG_UINT32 ui32Width,
+                                             IMG_UINT32 ui32Height,
+                                             IMG_UINT32 ui32StrideInBytes,
+                                             IMG_DEV_VIRTADDR sDevBaseAddr,
+                                             IMG_UINT32 ui32Size,
+                                             PDUMP_PIXEL_FORMAT ePixelFormat,
+                                             PDUMP_MEM_FORMAT eMemFormat,
+                                             IMG_UINT32 ui32PDumpFlags);
+       IMG_IMPORT PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR * pszFileName,
+                                              IMG_UINT32 ui32FileOffset,
+                                              IMG_UINT32 ui32Address,
+                                              IMG_UINT32 ui32Size,
+                                              IMG_UINT32 ui32PDumpFlags);
+       IMG_VOID PDUMP_REG_FUNC_NAME(IMG_UINT32 dwReg, IMG_UINT32 dwData);
+
+       IMG_VOID PDumpMsvdxRegRead(const IMG_CHAR * const pRegRegion,
+                                  const IMG_UINT32 dwRegOffset);
+
+       IMG_VOID PDumpMsvdxRegWrite(const IMG_CHAR * const pRegRegion,
+                                   const IMG_UINT32 dwRegOffset,
+                                   const IMG_UINT32 dwData);
+
+       PVRSRV_ERROR PDumpMsvdxRegPol(const IMG_CHAR * const pRegRegion,
+                                     const IMG_UINT32 ui32Offset,
+                                     const IMG_UINT32 ui32CheckFuncIdExt,
+                                     const IMG_UINT32 ui32RequValue,
+                                     const IMG_UINT32 ui32Enable,
+                                     const IMG_UINT32 ui32PollCount,
+                                     const IMG_UINT32 ui32TimeOut);
+
+       PVRSRV_ERROR PDumpMsvdxWriteRef(const IMG_CHAR * const pRegRegion,
+                                       const IMG_UINT32 ui32VLROffset,
+                                       const IMG_UINT32 ui32Physical);
+
+       IMG_VOID PDumpComment(IMG_CHAR * pszFormat, ...);
+       IMG_VOID PDumpCommentWithFlags(IMG_UINT32 ui32Flags,
+                                      IMG_CHAR * pszFormat, ...);
+       PVRSRV_ERROR PDumpRegPolKM(IMG_UINT32 ui32RegAddr,
+                                  IMG_UINT32 ui32RegValue,
+                                  IMG_UINT32 ui32Mask);
+       PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_UINT32 ui32RegAddr,
+                                           IMG_UINT32 ui32RegValue,
+                                           IMG_UINT32 ui32Mask,
+                                           IMG_UINT32 ui32Flags);
+       IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID);
+       IMG_IMPORT IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID);
+
+       IMG_VOID PDumpMallocPages(PVRSRV_DEVICE_TYPE eDeviceType,
+                                 IMG_UINT32 ui32DevVAddr,
+                                 IMG_CPU_VIRTADDR pvLinAddr,
+                                 IMG_HANDLE hOSMemHandle,
+                                 IMG_UINT32 ui32NumBytes,
+                                 IMG_HANDLE hUniqueTag);
+       IMG_VOID PDumpMallocPagesPhys(PVRSRV_DEVICE_TYPE eDeviceType,
+                                     IMG_UINT32 ui32DevVAddr,
+                                     IMG_PUINT32 pui32PhysPages,
+                                     IMG_UINT32 ui32NumPages,
+                                     IMG_HANDLE hUniqueTag);
+       IMG_VOID PDumpMallocPageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+                                     IMG_CPU_VIRTADDR pvLinAddr,
+                                     IMG_UINT32 ui32NumBytes,
+                                     IMG_HANDLE hUniqueTag);
+       IMG_VOID PDumpFreePages(struct _BM_HEAP_ *psBMHeap,
+                               IMG_DEV_VIRTADDR sDevVAddr,
+                               IMG_UINT32 ui32NumBytes,
+                               IMG_HANDLE hUniqueTag, IMG_BOOL bInterleaved);
+       IMG_VOID PDumpFreePageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+                                   IMG_CPU_VIRTADDR pvLinAddr,
+                                   IMG_UINT32 ui32NumBytes,
+                                   IMG_HANDLE hUniqueTag);
+       IMG_VOID PDumpPDReg(IMG_UINT32 ui32Reg,
+                           IMG_UINT32 ui32dwData, IMG_HANDLE hUniqueTag);
+       IMG_VOID PDumpPDRegWithFlags(IMG_UINT32 ui32Reg,
+                                    IMG_UINT32 ui32Data,
+                                    IMG_UINT32 ui32Flags,
+                                    IMG_HANDLE hUniqueTag);
+
+       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);
+
+       IMG_VOID PDumpTASignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+                                          IMG_UINT32 ui32TAKickCount,
+                                          IMG_BOOL bLastFrame,
+                                          IMG_UINT32 * pui32Registers,
+                                          IMG_UINT32 ui32NumRegisters);
+
+       IMG_VOID PDump3DSignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+                                          IMG_BOOL bLastFrame,
+                                          IMG_UINT32 * pui32Registers,
+                                          IMG_UINT32 ui32NumRegisters);
+
+       IMG_VOID PDumpRegRead(const IMG_UINT32 dwRegOffset,
+                             IMG_UINT32 ui32Flags);
+
+       IMG_VOID PDumpCycleCountRegRead(const IMG_UINT32 dwRegOffset,
+                                       IMG_BOOL bLastFrame);
+
+       IMG_VOID PDumpCounterRegisters(IMG_UINT32 ui32DumpFrameNum,
+                                      IMG_BOOL bLastFrame,
+                                      IMG_UINT32 * pui32Registers,
+                                      IMG_UINT32 ui32NumRegisters);
+
+       IMG_VOID PDumpEndInitPhase(IMG_VOID);
+
+       void PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+                     IMG_UINT32 ui32ROffOffset,
+                     IMG_UINT32 ui32WPosVal,
+                     IMG_UINT32 ui32PacketSize,
+                     IMG_UINT32 ui32BufferSize,
+                     IMG_UINT32 ui32Flags, IMG_HANDLE hUniqueTag);
+
+       IMG_VOID PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+       IMG_VOID PDumpIDL(IMG_UINT32 ui32Clocks);
+
+       IMG_VOID PDumpSuspendKM(IMG_VOID);
+       IMG_VOID PDumpResumeKM(IMG_VOID);
+
+#define PDUMPMEMPOL                            PDumpMemPolKM
+#define PDUMPMEM                               PDumpMemKM
+#define PDUMPMEM2                              PDumpMem2KM
+#define PDUMPINIT                              PDumpInit
+#define PDUMPDEINIT                            PDumpDeInit
+#define PDUMPISLASTFRAME               PDumpIsLastCaptureFrameKM
+#define PDUMPTESTFRAME                 PDumpIsCaptureFrameKM
+#define PDUMPTESTNEXTFRAME             PDumpTestNextFrame
+#define PDUMPREGWITHFLAGS              PDumpRegWithFlagsKM
+#define PDUMPREG                               PDUMP_REG_FUNC_NAME
+#define PDUMPCOMMENT                   PDumpComment
+#define PDUMPCOMMENTWITHFLAGS  PDumpCommentWithFlags
+#define PDUMPREGPOL                            PDumpRegPolKM
+#define PDUMPREGPOLWITHFLAGS   PDumpRegPolWithFlagsKM
+#define PDUMPMALLOCPAGES               PDumpMallocPages
+#define PDUMPMALLOCPAGETABLE   PDumpMallocPageTable
+#define PDUMPFREEPAGES                 PDumpFreePages
+#define PDUMPFREEPAGETABLE             PDumpFreePageTable
+#define PDUMPPDREG                             PDumpPDReg
+#define PDUMPPDREGWITHFLAGS            PDumpPDRegWithFlags
+#define PDUMPCBP                               PDumpCBP
+#define PDUMPMALLOCPAGESPHYS   PDumpMallocPagesPhys
+#define PDUMPENDINITPHASE              PDumpEndInitPhase
+#define PDUMPMSVDXREGWRITE             PDumpMsvdxRegWrite
+#define PDUMPMSVDXREGREAD              PDumpMsvdxRegRead
+#define PDUMPMSVDXPOL                  PDumpMsvdxRegPol
+#define PDUMPMSVDXWRITEREF             PDumpMsvdxWriteRef
+#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 PDUMPMEM2(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 PDUMPFREEPAGES(args...)
+#define PDUMPFREEPAGETABLE(args...)
+#define PDUMPPDREG(args...)
+#define PDUMPPDREGWITHFLAGS(args...)
+#define PDUMPSYNC(args...)
+#define PDUMPCOPYTOMEM(args...)
+#define PDUMPWRITE(args...)
+#define PDUMPCBP(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/pvr/pdumpdefs.h b/pvr/pdumpdefs.h
new file mode 100644 (file)
index 0000000..3515fa3
--- /dev/null
@@ -0,0 +1,92 @@
+/**********************************************************************
+ *
+ * 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_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/pvr/perproc.c b/pvr/perproc.c
new file mode 100644 (file)
index 0000000..f0cd7dd
--- /dev/null
@@ -0,0 +1,242 @@
+/**********************************************************************
+ *
+ * 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"
+#include "handle.h"
+#include "perproc.h"
+
+#define        HASH_TAB_INIT_SIZE 32
+
+static HASH_TABLE *psHashTab = IMG_NULL;
+
+static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+       PVRSRV_ERROR eError;
+       IMG_UINTPTR_T uiPerProc;
+
+       PVR_ASSERT(psPerProc != IMG_NULL);
+
+       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 (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 = 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)
+{
+       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);
+               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;
+
+               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_GENERIC;
+                       goto failure;
+               }
+
+               psPerProc->ui32PID = ui32PID;
+               psPerProc->ui32RefCount = 0;
+
+               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, ui32PID);
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%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:
+       (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"));
+                       }
+               }
+       }
+}
+
+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_GENERIC;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
+{
+
+       if (psHashTab != IMG_NULL) {
+
+               HASH_Delete(psHashTab);
+               psHashTab = IMG_NULL;
+       }
+
+       return PVRSRV_OK;
+}
diff --git a/pvr/perproc.h b/pvr/perproc.h
new file mode 100644 (file)
index 0000000..8c4d61d
--- /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 __PERPROC_H__
+#define __PERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+       typedef struct _PVRSRV_PER_PROCESS_DATA_ {
+               IMG_UINT32 ui32PID;
+               IMG_HANDLE hBlockAlloc;
+               PRESMAN_CONTEXT hResManContext;
+               IMG_HANDLE hPerProcData;
+               PVRSRV_HANDLE_BASE *psHandleBase;
+
+               IMG_BOOL bHandlesBatched;
+               IMG_UINT32 ui32RefCount;
+
+               IMG_BOOL bInitProcess;
+
+               IMG_HANDLE hOsPrivateData;
+       } PVRSRV_PER_PROCESS_DATA;
+
+       IMG_IMPORT PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32
+                                                                ui32PID);
+
+       PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID);
+       IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID);
+
+       PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID);
+       PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/power.c b/pvr/power.c
new file mode 100644 (file)
index 0000000..00a7957
--- /dev/null
@@ -0,0 +1,647 @@
+/**********************************************************************
+ *
+ * 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"
+
+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 %lx",
+                        eInitServerState));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       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 %lx",
+                        eInitServerState));
+               bReturnVal = IMG_FALSE;
+       }
+
+       return bReturnVal;
+}
+
+static IMG_BOOL _IsSystemStatePowered(PVR_POWER_STATE eSystemPowerState)
+{
+       return (IMG_BOOL) (eSystemPowerState < PVRSRV_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
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       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 ((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);
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
+                                        IMG_UINT32 ui32DeviceIndex,
+                                        PVR_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       PVRSRV_POWER_DEV *psPowerDevice;
+       PVR_POWER_STATE eNewDevicePowerState;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       psPowerDevice = psSysData->psPowerDeviceList;
+       while (psPowerDevice) {
+               if (bAllDevices
+                   || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex)) {
+                       eNewDevicePowerState =
+                           (eNewPowerState ==
+                            PVRSRV_POWER_Unspecified) ? 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;
+                               }
+                       }
+               }
+
+               psPowerDevice = psPowerDevice->psNext;
+       }
+
+       return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
+                                         IMG_UINT32 ui32DeviceIndex,
+                                         PVR_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       PVRSRV_POWER_DEV *psPowerDevice;
+       PVR_POWER_STATE eNewDevicePowerState;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       psPowerDevice = psSysData->psPowerDeviceList;
+       while (psPowerDevice) {
+               if (bAllDevices
+                   || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex)) {
+                       eNewDevicePowerState =
+                           (eNewPowerState ==
+                            PVRSRV_POWER_Unspecified) ? 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;
+                       }
+               }
+
+               psPowerDevice = psPowerDevice->psNext;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVSetDevicePowerStateCoreKM(IMG_UINT32 ui32DeviceIndex,
+                                            PVR_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError;
+       eError =
+           PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex,
+                                       eNewPowerState);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       eError =
+           PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex,
+                                        eNewPowerState);
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+                                            PVR_POWER_STATE eNewPowerState,
+                                            IMG_UINT32 ui32CallerID,
+                                            IMG_BOOL bRetainMutex)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       eError =
+           PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex,
+                                       eNewPowerState);
+       if (eError != PVRSRV_OK) {
+               goto Exit;
+       }
+
+       eError =
+           PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex,
+                                        eNewPowerState);
+
+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(PVR_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       SYS_DATA *psSysData;
+       PVR_POWER_STATE eNewDevicePowerState;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       if (_IsSystemStatePowered(eNewPowerState) !=
+           _IsSystemStatePowered(psSysData->eCurrentPowerState)) {
+               if (_IsSystemStatePowered(eNewPowerState)) {
+
+                       eNewDevicePowerState = PVRSRV_POWER_Unspecified;
+               } else {
+                       eNewDevicePowerState = PVRSRV_POWER_STATE_D3;
+               }
+
+               eError =
+                   PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0,
+                                               eNewDevicePowerState);
+               if (eError != PVRSRV_OK) {
+                       goto ErrorExit;
+               }
+       }
+
+       if (eNewPowerState != psSysData->eCurrentPowerState) {
+
+               eError = SysSystemPrePowerState(eNewPowerState);
+               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, eNewPowerState, eError));
+
+       psSysData->eFailedPowerState = eNewPowerState;
+
+       PVRSRVPowerUnlock(KERNEL_ID);
+
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVR_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       SYS_DATA *psSysData;
+       PVR_POWER_STATE eNewDevicePowerState;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               goto Exit;
+       }
+
+       if (eNewPowerState != psSysData->eCurrentPowerState) {
+
+               eError = SysSystemPostPowerState(eNewPowerState);
+               if (eError != PVRSRV_OK) {
+                       goto Exit;
+               }
+       }
+
+       if (_IsSystemStatePowered(eNewPowerState) !=
+           _IsSystemStatePowered(psSysData->eCurrentPowerState)) {
+               if (_IsSystemStatePowered(eNewPowerState)) {
+
+                       eNewDevicePowerState = PVRSRV_POWER_Unspecified;
+               } else {
+                       eNewDevicePowerState = PVRSRV_POWER_STATE_D3;
+               }
+
+               eError =
+                   PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0,
+                                                eNewDevicePowerState);
+               if (eError != PVRSRV_OK) {
+                       goto Exit;
+               }
+       }
+
+       PVR_DPF((PVR_DBG_WARNING,
+                "PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK",
+                psSysData->eCurrentPowerState, eNewPowerState));
+
+       psSysData->eCurrentPowerState = eNewPowerState;
+
+Exit:
+
+       PVRSRVPowerUnlock(KERNEL_ID);
+
+       if (_IsSystemStatePowered(eNewPowerState) &&
+           PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL)) {
+
+               PVRSRVCommandCompleteCallbacks();
+       }
+
+       return eError;
+}
+
+IMG_EXPORT PVRSRV_ERROR PVRSRVSetPowerStateKM(PVR_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       eError = PVRSRVSystemPrePowerStateKM(eNewPowerState);
+       if (eError != PVRSRV_OK) {
+               goto ErrorExit;
+       }
+
+       eError = PVRSRVSystemPostPowerStateKM(eNewPowerState);
+       if (eError != PVRSRV_OK) {
+               goto ErrorExit;
+       }
+
+       psSysData->eFailedPowerState = PVRSRV_POWER_Unspecified;
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
+                psSysData->eCurrentPowerState, eNewPowerState, eError));
+
+       psSysData->eFailedPowerState = eNewPowerState;
+
+       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,
+                                      PVR_POWER_STATE eCurrentPowerState,
+                                      PVR_POWER_STATE eDefaultPowerState)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       PVRSRV_POWER_DEV *psPowerDevice;
+
+       if (pfnPrePower == IMG_NULL && pfnPostPower == IMG_NULL) {
+               return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+       }
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                           sizeof(PVRSRV_POWER_DEV),
+                           (IMG_VOID **) & psPowerDevice, IMG_NULL);
+       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;
+
+       psPowerDevice->psNext = psSysData->psPowerDeviceList;
+       psSysData->psPowerDeviceList = psPowerDevice;
+
+       return (PVRSRV_OK);
+}
+
+PVRSRV_ERROR PVRSRVRemovePowerDevice(IMG_UINT32 ui32DeviceIndex)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       PVRSRV_POWER_DEV *psCurrent, *psPrevious;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       psCurrent = psSysData->psPowerDeviceList;
+       psPrevious = IMG_NULL;
+
+       while (psCurrent) {
+               if (psCurrent->ui32DeviceIndex == ui32DeviceIndex) {
+
+                       if (psPrevious) {
+                               psPrevious->psNext = psCurrent->psNext;
+                       } else {
+
+                               psSysData->psPowerDeviceList =
+                                   psCurrent->psNext;
+                       }
+
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psCurrent,
+                                 IMG_NULL);
+
+                       break;
+               } else {
+                       psPrevious = psCurrent;
+                       psCurrent = psCurrent->psNext;
+               }
+       }
+
+       return (PVRSRV_OK);
+}
+
+IMG_EXPORT IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       PVRSRV_POWER_DEV *psPowerDevice;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return IMG_FALSE;
+       }
+
+       if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID)
+           || OSIsResourceLocked(&psSysData->sPowerStateChangeResource,
+                                 ISR_ID)) {
+               return IMG_FALSE;
+       }
+
+       psPowerDevice = psSysData->psPowerDeviceList;
+       while (psPowerDevice) {
+               if (psPowerDevice->ui32DeviceIndex == ui32DeviceIndex) {
+                       return (IMG_BOOL) (psPowerDevice->eCurrentPowerState ==
+                                          PVRSRV_POWER_STATE_D0);
+               }
+
+               psPowerDevice = psPowerDevice->psNext;
+       }
+
+       return IMG_FALSE;
+}
+
+IMG_VOID PVRSRVDevicePreClockSpeedChange(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 = psSysData->psPowerDeviceList;
+       while (psPowerDevice) {
+               if (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex) {
+                       if (psPowerDevice->pfnPreClockSpeedChange) {
+                               eError =
+                                   psPowerDevice->
+                                   pfnPreClockSpeedChange(psPowerDevice->
+                                                          hDevCookie,
+                                                          bIdleDevice);
+                               if (eError != PVRSRV_OK) {
+                                       PVR_DPF((PVR_DBG_ERROR,
+                                                "PVRSRVDevicePreClockSpeedChange : Device %lu failed, error:0x%lx",
+                                                ui32DeviceIndex, eError));
+                               }
+                       }
+               }
+
+               psPowerDevice = psPowerDevice->psNext;
+       }
+}
+
+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 = psSysData->psPowerDeviceList;
+       while (psPowerDevice) {
+               if (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex) {
+                       if (psPowerDevice->pfnPostClockSpeedChange) {
+                               eError =
+                                   psPowerDevice->
+                                   pfnPostClockSpeedChange(psPowerDevice->
+                                                           hDevCookie,
+                                                           bIdleDevice);
+                               if (eError != PVRSRV_OK) {
+                                       PVR_DPF((PVR_DBG_ERROR,
+                                                "PVRSRVDevicePostClockSpeedChange : Device %lu failed, error:0x%lx",
+                                                ui32DeviceIndex, eError));
+                               }
+                       }
+               }
+
+               psPowerDevice = psPowerDevice->psNext;
+       }
+}
diff --git a/pvr/power.h b/pvr/power.h
new file mode 100644 (file)
index 0000000..a3fefd9
--- /dev/null
@@ -0,0 +1,119 @@
+/**********************************************************************
+ *
+ * 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;
+               PVR_POWER_STATE eDefaultPowerState;
+               PVR_POWER_STATE eCurrentPowerState;
+               struct _PVRSRV_POWER_DEV_TAG_ *psNext;
+
+       } 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,
+                                                    PVR_POWER_STATE
+                                                    eNewPowerState,
+                                                    IMG_UINT32 ui32CallerID,
+                                                    IMG_BOOL bRetainMutex);
+
+        IMG_IMPORT
+           PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVR_POWER_STATE
+                                                    eNewPowerState);
+        IMG_IMPORT PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVR_POWER_STATE
+                                                             eNewPowerState);
+
+        IMG_IMPORT
+           PVRSRV_ERROR PVRSRVSetPowerStateKM(PVR_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,
+                                                  PVR_POWER_STATE
+                                                  eCurrentPowerState,
+                                                  PVR_POWER_STATE
+                                                  eDefaultPowerState);
+
+        IMG_IMPORT
+           PVRSRV_ERROR PVRSRVRemovePowerDevice(IMG_UINT32 ui32DeviceIndex);
+
+        IMG_IMPORT IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+
+        IMG_IMPORT
+           IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+                                                    IMG_BOOL bIdleDevice,
+                                                    IMG_VOID * pvInfo);
+
+        IMG_IMPORT
+           IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32
+                                                     ui32DeviceIndex,
+                                                     IMG_BOOL bIdleDevice,
+                                                     IMG_VOID * pvInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/proc.c b/pvr/proc.c
new file mode 100644 (file)
index 0000000..f19a189
--- /dev/null
@@ -0,0 +1,360 @@
+/**********************************************************************
+ *
+ * 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 AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+
+#ifdef DEBUG
+int PVRDebugProcSetLevel(struct file *file, const char *buffer,
+                        unsigned long count, void *data);
+int PVRDebugProcGetLevel(char *page, char **start, off_t off, int count,
+                        int *eof, void *data);
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+int PVRProcSetPowerLevel(struct file *file, const char *buffer,
+                        unsigned long count, void *data);
+int PVRProcGetPowerLevel(char *page, char **start, off_t off, int count,
+                        int *eof, void *data);
+#endif
+#endif
+
+static struct proc_dir_entry *dir;
+
+static off_t procDumpSysNodes(char *buf, size_t size, off_t off);
+static off_t procDumpVersion(char *buf, size_t size, off_t off);
+
+off_t printAppend(char *buffer, size_t size, off_t off, const char *format, ...)
+{
+       int n;
+       int space = size - off;
+       va_list ap;
+
+       va_start(ap, format);
+
+       n = vsnprintf(buffer + off, space, format, ap);
+
+       va_end(ap);
+
+       if (n > space || n < 0) {
+               return size;
+       } else {
+               return off + n;
+       }
+}
+
+static int pvr_read_proc(char *page, char **start, off_t off,
+                        int count, int *eof, void *data)
+{
+       pvr_read_proc_t *pprn = data;
+
+       off_t len = pprn(page, count, off);
+
+       if (len == END_OF_FILE) {
+               len = 0;
+               *eof = 1;
+       } else if (!len) {
+               *start = (char *)0;
+       } else {
+               *start = (char *)1;
+       }
+
+       return len;
+}
+
+int CreateProcEntry(const char *name, read_proc_t rhandler,
+                   write_proc_t whandler, void *data)
+{
+       struct proc_dir_entry *file;
+       mode_t mode;
+
+       if (!dir) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "CreateProcEntry: cannot make proc entry /proc/pvr/%s: no parent",
+                        name));
+               return -ENOMEM;
+       }
+
+       mode = S_IFREG;
+
+       if (rhandler) {
+               mode |= S_IRUGO;
+       }
+
+       if (whandler) {
+               mode |= S_IWUSR;
+       }
+
+       file = create_proc_entry(name, mode, dir);
+
+       if (file) {
+               file->owner = THIS_MODULE;
+               file->read_proc = rhandler;
+               file->write_proc = whandler;
+               file->data = data;
+
+               PVR_DPF((PVR_DBG_MESSAGE, "Created /proc/pvr/%s", name));
+
+               return 0;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "CreateProcEntry: cannot make proc entry /proc/pvr/%s: no memory",
+                name));
+
+       return -ENOMEM;
+}
+
+int CreateProcReadEntry(const 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/pvr/%s: no parent",
+                        name));
+
+               return -ENOMEM;
+       }
+
+       file =
+           create_proc_read_entry(name, S_IFREG | S_IRUGO, dir, pvr_read_proc,
+                                  (void *)handler);
+
+       if (file) {
+               file->owner = THIS_MODULE;
+
+               return 0;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "CreateProcReadEntry: cannot make proc entry /proc/pvr/%s: no memory",
+                name));
+
+       return -ENOMEM;
+}
+
+int CreateProcEntries(void)
+{
+       dir = proc_mkdir("pvr", NULL);
+
+       if (!dir) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "CreateProcEntries: cannot make /proc/pvr directory"));
+
+               return -ENOMEM;
+       }
+
+       if (CreateProcReadEntry("queue", QueuePrintQueues) ||
+           CreateProcReadEntry("version", procDumpVersion) ||
+           CreateProcReadEntry("nodes", procDumpSysNodes)) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "CreateProcEntries: couldn't make /proc/pvr files"));
+
+               return -ENOMEM;
+       }
+#ifdef DEBUG
+       if (CreateProcEntry
+           ("debug_level", PVRDebugProcGetLevel, PVRDebugProcSetLevel, 0)) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "CreateProcEntries: couldn't make /proc/pvr/debug_level"));
+
+               return -ENOMEM;
+       }
+#ifdef PVR_MANUAL_POWER_CONTROL
+       if (CreateProcEntry
+           ("power_control", PVRProcGetPowerLevel, PVRProcSetPowerLevel, 0)) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "CreateProcEntries: couldn't make /proc/pvr/power_control"));
+
+               return -ENOMEM;
+       }
+#endif
+#endif
+
+       return 0;
+}
+
+void RemoveProcEntry(const char *name)
+{
+       if (dir) {
+               remove_proc_entry(name, dir);
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/pvr/%s", name));
+}
+
+void RemoveProcEntries(void)
+{
+#ifdef DEBUG
+       RemoveProcEntry("debug_level");
+#ifdef PVR_MANUAL_POWER_CONTROL
+       RemoveProcEntry("power_control");
+#endif
+#endif
+       RemoveProcEntry("queue");
+       RemoveProcEntry("nodes");
+       RemoveProcEntry("version");
+
+       while (dir->subdir) {
+               PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/pvr/%s",
+                        dir->subdir->name));
+
+               RemoveProcEntry(dir->subdir->name);
+       }
+
+       remove_proc_entry("pvr", NULL);
+}
+
+static off_t procDumpVersion(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);
+       }
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       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;
+}
+
+static const char *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+       switch (deviceType) {
+       default:
+               {
+                       static char text[10];
+
+                       sprintf(text, "?%x", deviceType);
+
+                       return text;
+               }
+       }
+}
+
+static const 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 char text[10];
+
+                       sprintf(text, "?%x", deviceClass);
+                       return text;
+               }
+       }
+}
+
+static
+off_t procDumpSysNodes(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");
+       }
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       for (psDevNode = psSysData->psDeviceNodeList;
+            --off && psDevNode; psDevNode = psDevNode->psNext) ;
+
+       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);
+}
diff --git a/pvr/proc.h b/pvr/proc.h
new file mode 100644 (file)
index 0000000..f00823e
--- /dev/null
@@ -0,0 +1,51 @@
+/**********************************************************************
+ *
+ * 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>
+
+#define END_OF_FILE (off_t) -1
+
+typedef off_t(pvr_read_proc_t) (char *, size_t, off_t);
+
+off_t printAppend(char *buffer, size_t size, off_t off, const char *format, ...)
+    __attribute__ ((format(printf, 4, 5)));
+
+int CreateProcEntries(void);
+
+int CreateProcReadEntry(const char *name, pvr_read_proc_t handler);
+
+int CreateProcEntry(const char *name, read_proc_t rhandler,
+                   write_proc_t whandler, void *data);
+
+void RemoveProcEntry(const char *name);
+
+void RemoveProcEntries(void);
+
+#endif
diff --git a/pvr/pvr_bridge.h b/pvr/pvr_bridge.h
new file mode 100644 (file)
index 0000000..abbe9c7
--- /dev/null
@@ -0,0 +1,1022 @@
+/**********************************************************************
+ *
+ * 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                   0
+#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_KV_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_CORE_CMD_LAST                            (PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+
+#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)
+
+#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST                        (PVRSRV_BRIDGE_MISC_CMD_LAST+1)
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+#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)
+#endif
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST                 (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST                  (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+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_PDREG                      PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR             PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_PDUMP_BUFFER_ARRAY               PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ       PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_PDUMP_3D_SIGNATURE_REGISTERS     PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_PDUMP_COUNTER_REGISTERS  PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_PDUMP_TA_SIGNATURE_REGISTERS     PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST                   (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+20)
+#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_DISPCLASS_CMD_LAST               (PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+
+#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_LAST_NON_DEVICE_CMD              (PVRSRV_BRIDGE_EVENT_OBJECT_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_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_UINT32 ui32Size;
+               IMG_UINT32 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_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_UINT32 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_KV_TO_MMAP_DATA_TAG {
+               IMG_UINT32 ui32BridgeFlags;
+               IMG_VOID *pvKVIndexAddress;
+               IMG_UINT32 ui32Bytes;
+       } PVRSRV_BRIDGE_IN_KV_TO_MMAP_DATA;
+
+       typedef struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM_TAG {
+               IMG_UINT32 ui32BridgeFlags;
+               IMG_HANDLE hDevMemHeap;
+               IMG_DEV_VIRTADDR *psDevVAddr;
+               IMG_UINT32 ui32Size;
+               IMG_UINT32 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;
+               PVRSRV_KERNEL_MEM_INFO *psSrcKernelMemInfo;
+               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_KERNEL_SYNC_INFO *psDstKernelSyncInfo;
+               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;
+
+       } 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;
+               PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+               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;
+               IMG_BOOL bLastFrame;
+               IMG_BOOL bOverwrite;
+
+       } 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 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;
+               PVRSRV_HWREG sHWReg;
+               IMG_UINT32 ui32Flags;
+
+       } PVRSRV_BRIDGE_IN_PDUMP_DUMPREG;
+
+       typedef struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL_TAG {
+               IMG_UINT32 ui32BridgeFlags;
+               PVRSRV_HWREG sHWReg;
+               IMG_UINT32 ui32Mask;
+               IMG_UINT32 ui32Flags;
+       } 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_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+               IMG_UINT32 ui32FileOffset;
+               IMG_UINT32 ui32Width;
+               IMG_UINT32 ui32Height;
+               IMG_UINT32 ui32StrideInBytes;
+               IMG_DEV_VIRTADDR sDevBaseAddr;
+               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_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+               IMG_UINT32 ui32FileOffset;
+               IMG_UINT32 ui32Address;
+               IMG_UINT32 ui32Size;
+               IMG_UINT32 ui32Flags;
+
+       } 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_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_VOID *pvLinAddr;
+               IMG_UINT32 ui32ByteSize;
+               IMG_UINT32 ui32PageOffset;
+               IMG_BOOL bPhysContig;
+               IMG_UINT32 ui32NumPageTableEntries;
+               IMG_SYS_PHYADDR *psSysPAddr;
+
+       } 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_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_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_KERNEL_SYNC_INFO *psKernelSyncInfo;
+               PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+               PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+       } PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM;
+
+       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_UINT32 ui32Total;
+               IMG_UINT32 ui32Free;
+               IMG_UINT32 ui32LargestBlock;
+
+       } PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM;
+
+#include "pvrmmap.h"
+       typedef struct PVRSRV_BRIDGE_OUT_KV_TO_MMAP_DATA_TAG {
+               PVRSRV_ERROR eError;
+
+               IMG_UINT32 ui32MMapOffset;
+
+               IMG_UINT32 ui32ByteOffset;
+
+               IMG_UINT32 ui32RealByteSize;
+
+       } PVRSRV_BRIDGE_OUT_KV_TO_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_UINT32 ui32Total;
+               IMG_UINT32 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_UINT32 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_KERNEL_SYNC_INFO *psKernelSyncInfo;
+               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;
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/pvr_bridge_k.c b/pvr/pvr_bridge_k.c
new file mode 100644 (file)
index 0000000..bf668fb
--- /dev/null
@@ -0,0 +1,365 @@
+/**********************************************************************
+ *
+ * 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 "sgx_bridge.h"
+
+#include "bridged_pvr_bridge.h"
+
+#ifdef MODULE_TEST
+#include "pvr_test_bridge.h"
+#include "kern_test.h"
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+static off_t printLinuxBridgeStats(char *buffer, size_t size, off_t off);
+#endif
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+PVRSRV_ERROR LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+       {
+               int iStatus;
+               iStatus =
+                   CreateProcReadEntry("bridge_stats", printLinuxBridgeStats);
+               if (iStatus != 0) {
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+       }
+#endif
+       return CommonBridgeInit();
+}
+
+IMG_VOID LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+       RemoveProcEntry("bridge_stats");
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+static off_t printLinuxBridgeStats(char *buffer, size_t count, off_t off)
+{
+       PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry;
+       off_t Ret;
+
+       LinuxLockMutex(&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:
+       LinuxUnLockMutex(&gPVRSRVLock);
+       return Ret;
+}
+#endif
+
+int
+PVRSRV_BridgeDispatchKM(struct inode *inode,
+                       struct file *file, unsigned int cmd, unsigned long arg)
+{
+       IMG_UINT32 ui32BridgeID = PVRSRV_GET_BRIDGE_ID(cmd);
+       PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM =
+           (PVRSRV_BRIDGE_PACKAGE *) arg;
+       PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+       IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+       PVRSRV_PER_PROCESS_DATA *psPerProc;
+       int err = -EFAULT;
+
+       LinuxLockMutex(&gPVRSRVLock);
+
+       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,
+                          &sBridgePackageKM,
+                          psBridgePackageUM, sizeof(PVRSRV_BRIDGE_PACKAGE))
+           != PVRSRV_OK) {
+               goto unlock_and_return;
+       }
+#ifdef MODULE_TEST
+       switch (cmd) {
+       case PVRSRV_BRIDGE_SERVICES_TEST_MEM1:
+               {
+                       PVRSRV_ERROR eError = MemTest1();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+       case PVRSRV_BRIDGE_SERVICES_TEST_MEM2:
+               {
+                       PVRSRV_ERROR eError = MemTest2();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+
+       case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE:
+               {
+                       PVRSRV_ERROR eError = ResourceTest();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+
+       case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT:
+               {
+                       PVRSRV_ERROR eError = EventObjectTest();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+
+       case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING:
+               {
+                       PVRSRV_ERROR eError = MemMappingTest();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+
+       case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID:
+               {
+                       PVRSRV_ERROR eError = ProcessIDTest();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+
+       case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS:
+               {
+                       PVRSRV_ERROR eError = ClockusWaitusTest();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+
+       case PVRSRV_BRIDGE_SERVICES_TEST_TIMER:
+               {
+                       PVRSRV_ERROR eError = TimerTest();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+
+       case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV:
+               {
+                       PVRSRV_ERROR eError = PrivSrvTest();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   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(sBridgePackageKM.pvParamIn,
+                                        sBridgePackageKM.pvParamOut,
+                                        psPerProc);
+
+                       *(PVRSRV_ERROR *) sBridgePackageKM.pvParamOut = eError;
+                       err = 0;
+                       goto unlock_and_return;
+               }
+
+       case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT:
+               {
+                       PVRSRV_ERROR eError = PowerMgmtTest();
+                       if (sBridgePackageKM.ui32OutBufferSize ==
+                           sizeof(PVRSRV_BRIDGE_RETURN)) {
+                               PVRSRV_BRIDGE_RETURN *pReturn =
+                                   (PVRSRV_BRIDGE_RETURN *) sBridgePackageKM.
+                                   pvParamOut;
+                               pReturn->eError = eError;
+                       }
+               }
+               err = 0;
+               goto unlock_and_return;
+
+       }
+#endif
+
+       if (ui32BridgeID !=
+           PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES)) {
+               PVRSRV_ERROR eError;
+
+               eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+                                           (IMG_PVOID *) & psPerProc,
+                                           sBridgePackageKM.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;
+               }
+       }
+
+       sBridgePackageKM.ui32BridgeID =
+           PVRSRV_GET_BRIDGE_ID(sBridgePackageKM.ui32BridgeID);
+
+       err = BridgedDispatchKM(psPerProc, &sBridgePackageKM);
+
+unlock_and_return:
+       LinuxUnLockMutex(&gPVRSRVLock);
+       return err;
+}
diff --git a/pvr/pvr_bridge_km.h b/pvr/pvr_bridge_km.h
new file mode 100644 (file)
index 0000000..a144092
--- /dev/null
@@ -0,0 +1,355 @@
+/**********************************************************************
+ *
+ * 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_UINT32
+                                                                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
+#if defined(PVR_SECURE_HANDLES)
+                                                                    ,
+                                                                    IMG_BOOL *
+                                                                    pbShared
+#endif
+           );
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE
+                                                                     hDevCookie,
+                                                                     IMG_HANDLE
+                                                                     hDevMemContext,
+                                                                     IMG_BOOL *
+                                                                     pbCreated);
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE
+                                                                  hDevCookie,
+                                                                  IMG_HANDLE
+                                                                  hDevMemContext,
+                                                                  IMG_UINT32 *
+                                                                  pui32ClientHeapCount,
+                                                                  PVRSRV_HEAP_INFO
+                                                                  * psHeapInfo
+#if defined(PVR_SECURE_HANDLES)
+                                                                  ,
+                                                                  IMG_BOOL *
+                                                                  pbShared
+#endif
+           );
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMemKM(IMG_HANDLE
+                                                            hDevCookie,
+                                                            PVRSRV_PER_PROCESS_DATA
+                                                            * psPerProc,
+                                                            IMG_HANDLE
+                                                            hDevMemHeap,
+                                                            IMG_UINT32
+                                                            ui32Flags,
+                                                            IMG_UINT32
+                                                            ui32Size,
+                                                            IMG_UINT32
+                                                            ui32Alignment,
+                                                            PVRSRV_KERNEL_MEM_INFO
+                                                            ** ppsMemInfo);
+
+        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_UINT32
+                                                                     ui32Size,
+                                                                     IMG_UINT32
+                                                                     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_UINT32
+                                                           ui32ByteSize,
+                                                           IMG_UINT32
+                                                           ui32PageOffset,
+                                                           IMG_BOOL
+                                                           bPhysContig,
+                                                           IMG_SYS_PHYADDR *
+                                                           psSysAddr,
+                                                           IMG_VOID *
+                                                           pvLinAddr,
+                                                           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);
+        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 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_UINT32 *
+                                                              pui32Total,
+                                                              IMG_UINT32 *
+                                                              pui32Free,
+                                                              IMG_UINT32 *
+                                                              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);
+
+       PVRSRV_ERROR PVRSRVGetFBStatsKM(IMG_UINT32 * pui32Total,
+                                       IMG_UINT32 * pui32Available);
+
+       IMG_IMPORT PVRSRV_ERROR
+           PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+                                        IMG_UINT32 ui32Flags,
+                                        IMG_UINT32 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/pvr/pvr_debug.c b/pvr/pvr_debug.c
new file mode 100644 (file)
index 0000000..f56b2a1
--- /dev/null
@@ -0,0 +1,187 @@
+/**********************************************************************
+ *
+ * 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 AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <stdarg.h>
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "proc.h"
+
+#if defined(DEBUG) || defined(TIMING)
+
+IMG_UINT32 gPVRDebugLevel = 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, bDebug;
+#if !defined(__sh__)
+       IMG_CHAR *pszLeafName;
+
+       pszLeafName = (char *)strrchr(pszFileName, '\\');
+
+       if (pszLeafName) {
+               pszFileName = pszLeafName;
+       }
+#endif
+
+       bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+       bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+       if (bTrace || bDebug) {
+               va_list vaArgs;
+               static char szBuffer[256];
+
+               va_start(vaArgs, pszFormat);
+
+               if (bDebug) {
+                       switch (ui32DebugLevel) {
+                       case DBGPRIV_FATAL:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Fatal): ");
+                                       break;
+                               }
+                       case DBGPRIV_ERROR:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Error): ");
+                                       break;
+                               }
+                       case DBGPRIV_WARNING:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Warning): ");
+                                       break;
+                               }
+                       case DBGPRIV_MESSAGE:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Message): ");
+                                       break;
+                               }
+                       case DBGPRIV_VERBOSE:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Verbose): ");
+                                       break;
+                               }
+                       default:
+                               {
+                                       strcpy(szBuffer,
+                                              "PVR_K:(Unknown message level)");
+                                       break;
+                               }
+                       }
+               } else {
+                       strcpy(szBuffer, "PVR_K: ");
+               }
+
+               vsprintf(&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
+
+               if (!bTrace) {
+                       sprintf(&szBuffer[strlen(szBuffer)], " [%d, %s]",
+                               (int)ui32Line, pszFileName);
+               }
+
+               printk(KERN_INFO "%s\n", szBuffer);
+
+               va_end(vaArgs);
+       }
+}
+
+void PVRSRVDebugAssertFail(const IMG_CHAR * pszFile, IMG_UINT32 uLine)
+{
+       PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine,
+                         "Debug assertion failed!");
+       BUG();
+}
+
+void PVRSRVTrace(const IMG_CHAR * pszFormat, ...)
+{
+       static IMG_CHAR szMessage[PVR_MAX_DEBUG_MESSAGE_LEN + 1];
+       IMG_CHAR *pszEndOfMessage = IMG_NULL;
+       va_list ArgList;
+
+       strncpy(szMessage, "PVR: ", PVR_MAX_DEBUG_MESSAGE_LEN);
+
+       pszEndOfMessage = &szMessage[strlen(szMessage)];
+
+       va_start(ArgList, pszFormat);
+       vsprintf(pszEndOfMessage, pszFormat, ArgList);
+       va_end(ArgList);
+
+       strcat(szMessage, "\n");
+
+       printk(KERN_INFO "%s", szMessage);
+}
+
+void PVRDebugSetLevel(IMG_UINT32 uDebugLevel)
+{
+       printk(KERN_INFO "PVR: Setting Debug Level = 0x%x\n",
+              (unsigned int)uDebugLevel);
+
+       gPVRDebugLevel = uDebugLevel;
+}
+
+int PVRDebugProcSetLevel(struct file *file, const char *buffer,
+                        unsigned long count, void *data)
+{
+#define        _PROC_SET_BUFFER_SZ             2
+       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);
+}
+
+int PVRDebugProcGetLevel(char *page, char **start, off_t off, int count,
+                        int *eof, void *data)
+{
+       if (off == 0) {
+               *start = (char *)1;
+               return printAppend(page, count, 0, "%lu\n", gPVRDebugLevel);
+       }
+       *eof = 1;
+       return 0;
+}
+
+#endif
diff --git a/pvr/pvr_debug.h b/pvr/pvr_debug.h
new file mode 100644 (file)
index 0000000..3b0d026
--- /dev/null
@@ -0,0 +1,112 @@
+/**********************************************************************
+ *
+ * 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          0x01
+#define DBGPRIV_ERROR          0x02
+#define DBGPRIV_WARNING                0x04
+#define DBGPRIV_MESSAGE                0x08
+#define DBGPRIV_VERBOSE                0x10
+#define DBGPRIV_CALLTRACE      0x20
+#define DBGPRIV_ALLOC          0x40
+#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__
+
+#if defined(DEBUG)
+#if !defined (QAC_ANALYSE)
+#define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+#else
+       void __cdecl _assert(void *, void *, unsigned);
+
+#define PVR_ASSERT(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) )
+#endif
+
+#define PVR_DPF(X)             PVRSRVDebugPrintf X
+#define PVR_TRACE(X)   PVRSRVTrace X
+
+       IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *
+                                                              pszFile,
+                                                              IMG_UINT32
+                                                              ui32Line);
+
+       IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32
+                                                          ui32DebugLevel,
+                                                          const IMG_CHAR *
+                                                          pszFileName,
+                                                          IMG_UINT32 ui32Line,
+                                                          const IMG_CHAR *
+                                                          pszFormat, ...);
+
+       IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR * pszFormat,
+                                                    ...);
+
+       IMG_VOID PVRSRVDebugSetLevel(IMG_UINT32 uDebugLevel);
+
+#define PVR_DBG_BREAK
+
+#else
+
+#if defined(TIMING)
+
+#define PVR_ASSERT(EXPR)
+#define PVR_DPF(X)
+#define PVR_TRACE(X)   PVRSRVTrace X
+#define PVR_DBG_BREAK
+
+       IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR * pszFormat,
+                                                    ...);
+
+#else
+
+#define PVR_ASSERT(EXPR)
+#define PVR_DPF(X)
+#define PVR_TRACE(X)
+#define PVR_DBG_BREAK
+
+#endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/pvrmmap.h b/pvr/pvrmmap.h
new file mode 100644 (file)
index 0000000..7b16554
--- /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 PVRMMAPMapKernelPtr(IMG_HANDLE hModule, IMG_VOID ** ppvLinAddr,
+                                IMG_VOID * pvKVIndexAddress,
+                                IMG_UINT32 ui32Bytes);
+
+IMG_BOOL PVRMMAPRemoveMapping(IMG_VOID * pvUserAddress, IMG_UINT32 ui32Bytes);
+
+#endif
diff --git a/pvr/pvrmodule.h b/pvr/pvrmodule.h
new file mode 100644 (file)
index 0000000..dcf517b
--- /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/pvr/pvrsrv.c b/pvr/pvrsrv.c
new file mode 100644 (file)
index 0000000..50e39e7
--- /dev/null
@@ -0,0 +1,958 @@
+/**********************************************************************
+ *
+ * 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 "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "ra.h"
+
+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_GENERIC;
+}
+
+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_GENERIC;
+}
+
+#ifndef ReadHWReg
+IMG_EXPORT
+    IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+       return *(volatile IMG_UINT32 *)((IMG_UINT32) 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",
+                pvLinRegBaseAddr, ui32Offset, ui32Value));
+
+       *(IMG_UINT32 *) ((IMG_UINT32) 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++;
+       }
+}
+#endif
+
+IMG_EXPORT
+    PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *
+                                                      pui32NumDevices,
+                                                      PVRSRV_DEVICE_IDENTIFIER
+                                                      * psDevIdList)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_UINT32 i;
+
+       if (!pui32NumDevices || !psDevIdList) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVEnumerateDevicesKM: Invalid params"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVEnumerateDevicesKM: Failed to get SysData"));
+               return eError;
+       }
+
+       for (i = 0; i < PVRSRV_MAX_DEVICES; i++) {
+               psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+       }
+
+       *pui32NumDevices = 0;
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       for (i = 0; psDeviceNode != IMG_NULL; i++) {
+
+               if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT) {
+
+                       *psDevIdList++ = psDeviceNode->sDevId;
+
+                       (*pui32NumDevices)++;
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       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;
+       }
+
+       gpsSysData->eCurrentPowerState = PVRSRV_POWER_STATE_D0;
+       gpsSysData->eFailedPowerState = PVRSRV_POWER_Unspecified;
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(PVRSRV_EVENTOBJECT),
+                      (IMG_VOID **) & psSysData->psGlobalEventObject,
+                      0) != PVRSRV_OK) {
+
+               goto Error;
+       }
+
+       if (OSEventObjectCreate
+           ("PVRSRV_GLOBAL_EVENTOBJECT",
+            psSysData->psGlobalEventObject) != PVRSRV_OK) {
+               goto Error;
+       }
+
+       return eError;
+
+Error:
+       PVRSRVDeInit(psSysData);
+       return eError;
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+
+       if (psSysData->psGlobalEventObject) {
+               OSEventObjectDestroy(psSysData->psGlobalEventObject);
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                         sizeof(PVRSRV_EVENTOBJECT),
+                         psSysData->psGlobalEventObject, 0);
+       }
+
+       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) != 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,
+                         0, 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);
+
+       psDeviceNode->psNext = psSysData->psDeviceNodeList;
+       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"));
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVInitialiseDevice: Failed to get SysData"));
+               return (eError);
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+
+       while (psDeviceNode) {
+               if (psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex) {
+                       goto FoundDevice;
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVInitialiseDevice: requested device is not present"));
+       return PVRSRV_ERROR_INIT_FAILURE;
+
+FoundDevice:
+
+       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;
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       SYS_DATA *psSysData;
+       PVRSRV_ERROR eError;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVFinaliseSystem: Failed to get SysData"));
+               return (eError);
+       }
+
+       if (bInitSuccessful) {
+               eError = SysFinalise();
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "PVRSRVFinaliseSystem: SysFinalise failed (%d)",
+                                eError));
+                       return eError;
+               }
+
+               psDeviceNode = psSysData->psDeviceNodeList;
+               while (psDeviceNode) {
+                       eError =
+                           PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.
+                                                       ui32DeviceIndex,
+                                                       PVRSRV_POWER_Unspecified,
+                                                       KERNEL_ID, IMG_FALSE);
+                       if (eError != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)",
+                                        psDeviceNode->sDevId.ui32DeviceIndex));
+                       }
+                       psDeviceNode = psDeviceNode->psNext;
+               }
+       }
+
+       PDUMPENDINITPHASE();
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM(IMG_UINT32 ui32DevIndex,
+                                                       PVRSRV_DEVICE_TYPE
+                                                       eDeviceType,
+                                                       IMG_HANDLE *
+                                                       phDevCookie)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       SYS_DATA *psSysData;
+       PVRSRV_ERROR eError;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVAcquireDeviceDataKM: Failed to get SysData"));
+               return (eError);
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+
+       if (eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN) {
+               while (psDeviceNode) {
+                       if (psDeviceNode->sDevId.eDeviceType == eDeviceType) {
+                               goto FoundDevice;
+                       }
+                       psDeviceNode = psDeviceNode->psNext;
+               }
+       } else {
+               while (psDeviceNode) {
+                       if (psDeviceNode->sDevId.ui32DeviceIndex ==
+                           ui32DevIndex) {
+                               goto FoundDevice;
+                       }
+                       psDeviceNode = psDeviceNode->psNext;
+               }
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVAcquireDeviceDataKM: requested device is not present"));
+       return PVRSRV_ERROR_INIT_FAILURE;
+
+FoundDevice:
+
+       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;
+       PVRSRV_DEVICE_NODE **ppsDevNode;
+       SYS_DATA *psSysData;
+       PVRSRV_ERROR eError;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVDeinitialiseDevice: Failed to get SysData"));
+               return (eError);
+       }
+
+       ppsDevNode = &psSysData->psDeviceNodeList;
+       while (*ppsDevNode) {
+               if ((*ppsDevNode)->sDevId.ui32DeviceIndex == ui32DevIndex) {
+                       psDeviceNode = *ppsDevNode;
+                       goto FoundDevice;
+               }
+               ppsDevNode = &((*ppsDevNode)->psNext);
+       }
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "PVRSRVDeinitialiseDevice: requested device %d is not present",
+                ui32DevIndex));
+
+       return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+       eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+                                            PVRSRV_POWER_STATE_D3,
+                                            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;
+
+       *ppsDevNode = psDeviceNode->psNext;
+
+       FreeDeviceID(psSysData, ui32DevIndex);
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, 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 ui32Waitus,
+                                            IMG_UINT32 ui32Tries)
+{
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0, uiCurrent = 0, uiMaxTime;
+
+       uiMaxTime = ui32Tries * ui32Waitus;
+
+       do {
+               if ((*pui32LinMemAddr & ui32Mask) == ui32Value) {
+                       return PVRSRV_OK;
+               }
+
+               if (bStart == IMG_FALSE) {
+                       bStart = IMG_TRUE;
+                       uiStart = OSClockus();
+               }
+
+               OSWaitus(ui32Waitus);
+
+               uiCurrent = OSClockus();
+               if (uiCurrent < uiStart) {
+
+                       uiStart = 0;
+               }
+
+       } while ((uiCurrent - uiStart) < uiMaxTime);
+
+       return PVRSRV_ERROR_GENERIC;
+}
+
+#if defined (USING_ISR_INTERRUPTS)
+
+extern IMG_UINT32 gui32EventStatusServicesByISR;
+
+PVRSRV_ERROR PollForInterruptKM(IMG_UINT32 ui32Value,
+                               IMG_UINT32 ui32Mask,
+                               IMG_UINT32 ui32Waitus, IMG_UINT32 ui32Tries)
+{
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0, uiCurrent = 0, uiMaxTime;
+
+       uiMaxTime = ui32Tries * ui32Waitus;
+
+       do {
+               if ((gui32EventStatusServicesByISR & ui32Mask) == ui32Value) {
+                       gui32EventStatusServicesByISR = 0;
+                       return PVRSRV_OK;
+               }
+
+               if (bStart == IMG_FALSE) {
+                       bStart = IMG_TRUE;
+                       uiStart = OSClockus();
+               }
+
+               OSWaitus(ui32Waitus);
+
+               uiCurrent = OSClockus();
+               if (uiCurrent < uiStart) {
+
+                       uiStart = 0;
+               }
+
+       } while ((uiCurrent - uiStart) < uiMaxTime);
+
+       return PVRSRV_ERROR_GENERIC;
+}
+#endif
+
+IMG_EXPORT
+    PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO * psMiscInfo)
+{
+       SYS_DATA *psSysData;
+       PVRSRV_ERROR eError;
+
+       if (!psMiscInfo) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVGetMiscInfoKM: invalid parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
+                                            |
+                                            PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
+                                            | PVRSRV_MISC_INFO_MEMSTATS_PRESENT
+                                            |
+                                            PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVGetMiscInfoKM: invalid state request flags"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVGetMiscInfoKM: Failed to get SysData"));
+               return eError;
+       }
+
+       psMiscInfo->ui32StatePresent = 0;
+
+       if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT)
+           && psSysData->pvSOCTimerRegisterKM) {
+               psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
+               psMiscInfo->pvSOCTimerRegisterKM =
+                   psSysData->pvSOCTimerRegisterKM;
+               psMiscInfo->hSOCTimerRegisterOSMemHandle =
+                   psSysData->hSOCTimerRegisterOSMemHandle;
+       }
+
+       if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT)
+           && psSysData->pvSOCClockGateRegsBase) {
+               psMiscInfo->ui32StatePresent |=
+                   PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
+               psMiscInfo->pvSOCClockGateRegs =
+                   psSysData->pvSOCClockGateRegsBase;
+               psMiscInfo->ui32SOCClockGateRegsSize =
+                   psSysData->ui32SOCClockGateRegsSize;
+       }
+
+       if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT)
+           && psMiscInfo->pszMemoryStr) {
+               RA_ARENA **ppArena;
+               BM_HEAP *psBMHeap;
+               BM_CONTEXT *psBMContext;
+               PVRSRV_DEVICE_NODE *psDeviceNode;
+               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++;
+               }
+
+               psDeviceNode = psSysData->psDeviceNodeList;
+               while (psDeviceNode) {
+                       CHECK_SPACE(ui32StrLen);
+                       i32Count =
+                           OSSNPrintf(pszStr, 100, "\n\nDevice Type %d:\n",
+                                      psDeviceNode->sDevId.eDeviceType);
+                       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+                       if (psDeviceNode->sDevMemoryInfo.pBMKernelContext) {
+                               CHECK_SPACE(ui32StrLen);
+                               i32Count =
+                                   OSSNPrintf(pszStr, 100,
+                                              "\nKernel Context:\n");
+                               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+                               psBMHeap =
+                                   psDeviceNode->sDevMemoryInfo.
+                                   pBMKernelContext->psBMHeap;
+                               while (psBMHeap) {
+                                       if (psBMHeap->pImportArena) {
+                                               RA_GetStats(psBMHeap->
+                                                           pImportArena,
+                                                           &pszStr,
+                                                           &ui32StrLen);
+                                       }
+
+                                       if (psBMHeap->pVMArena) {
+                                               RA_GetStats(psBMHeap->pVMArena,
+                                                           &pszStr,
+                                                           &ui32StrLen);
+                                       }
+                                       psBMHeap = psBMHeap->psNext;
+                               }
+                       }
+
+                       psBMContext = psDeviceNode->sDevMemoryInfo.pBMContext;
+                       while (psBMContext) {
+                               CHECK_SPACE(ui32StrLen);
+                               i32Count =
+                                   OSSNPrintf(pszStr, 100,
+                                              "\nApplication Context (hDevMemContext) 0x%08X:\n",
+                                              (IMG_HANDLE) psBMContext);
+                               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+                               psBMHeap = psBMContext->psBMHeap;
+                               while (psBMHeap) {
+                                       if (psBMHeap->pImportArena) {
+                                               RA_GetStats(psBMHeap->
+                                                           pImportArena,
+                                                           &pszStr,
+                                                           &ui32StrLen);
+                                       }
+
+                                       if (psBMHeap->pVMArena) {
+                                               RA_GetStats(psBMHeap->pVMArena,
+                                                           &pszStr,
+                                                           &ui32StrLen);
+                                       }
+                                       psBMHeap = psBMHeap->psNext;
+                               }
+                               psBMContext = psBMContext->psNext;
+                       }
+                       psDeviceNode = psDeviceNode->psNext;
+               }
+
+               i32Count = OSSNPrintf(pszStr, 100, "\n\0");
+               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+       }
+
+       if ((psMiscInfo->
+            ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
+           && psSysData->psGlobalEventObject) {
+               psMiscInfo->ui32StatePresent |=
+                   PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
+               psMiscInfo->sGlobalEventObject =
+                   *psSysData->psGlobalEventObject;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFBStatsKM(IMG_UINT32 * pui32Total,
+                                            IMG_UINT32 * pui32Available)
+{
+       IMG_UINT32 ui32Total = 0, i = 0;
+       IMG_UINT32 ui32Available = 0;
+
+       *pui32Total = 0;
+       *pui32Available = 0;
+
+       while (BM_ContiguousStatistics(i, &ui32Total, &ui32Available) ==
+              IMG_TRUE) {
+               *pui32Total += ui32Total;
+               *pui32Available += ui32Available;
+
+               i++;
+       }
+
+       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;
+}
+
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID * pvSysData)
+{
+       SYS_DATA *psSysData = pvSysData;
+       IMG_BOOL bStatus = IMG_FALSE;
+       IMG_UINT32 ui32InterruptSource;
+       IMG_UINT32 ui32ClearInterrupts = 0;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       if (!psSysData) {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+               goto out;
+       }
+
+       ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
+
+       if (ui32InterruptSource == 0) {
+               goto out;
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       while (psDeviceNode != IMG_NULL) {
+               if (psDeviceNode->pfnDeviceISR != IMG_NULL) {
+                       if (ui32InterruptSource & psDeviceNode->
+                           ui32SOCInterruptBit) {
+                               if ((*psDeviceNode->
+                                    pfnDeviceISR) (psDeviceNode->pvISRData)) {
+
+                                       bStatus = IMG_TRUE;
+                               }
+
+                               ui32ClearInterrupts |=
+                                   psDeviceNode->ui32SOCInterruptBit;
+                       }
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       SysClearInterrupts(psSysData, ui32ClearInterrupts);
+
+out:
+       return bStatus;
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID * pvSysData)
+{
+       SYS_DATA *psSysData = pvSysData;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       if (!psSysData) {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
+               return;
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       while (psDeviceNode != IMG_NULL) {
+               if (psDeviceNode->pfnDeviceMISR != IMG_NULL) {
+                       (*psDeviceNode->pfnDeviceMISR) (psDeviceNode->
+                                                       pvISRData);
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       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);
+               }
+       }
+}
+
+IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID)
+{
+       return PVRSRVPerProcessDataConnect(ui32PID);
+}
+
+IMG_EXPORT IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
+{
+       PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena,
+                                                       IMG_PBYTE pbyBuffer,
+                                                       IMG_UINT32 * puiBufSize,
+                                                       IMG_BOOL bSave)
+{
+       IMG_UINT32 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);
+}
diff --git a/pvr/pvrversion.h b/pvr/pvrversion.h
new file mode 100644 (file)
index 0000000..aab880a
--- /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 _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 3
+#define PVRVERSION_BRANCH 13
+#define PVRVERSION_BUILD 1607
+#define PVRVERSION_STRING "1.3.13.1607"
+#define PVRVERSION_FILE "eurasiacon.pj"
+
+#endif
diff --git a/pvr/queue.c b/pvr/queue.c
new file mode 100644 (file)
index 0000000..9bb8360
--- /dev/null
@@ -0,0 +1,893 @@
+/**********************************************************************
+ *
+ * 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"
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include "proc.h"
+
+static int
+QueuePrintCommands(PVRSRV_QUEUE_INFO * psQueue, char *buffer, size_t size)
+{
+       off_t off = 0;
+       int cmds = 0;
+       IMG_UINT32 ui32ReadOffset = psQueue->ui32ReadOffset;
+       IMG_UINT32 ui32WriteOffset = psQueue->ui32WriteOffset;
+       PVRSRV_COMMAND *psCmd;
+
+       while (ui32ReadOffset != ui32WriteOffset) {
+               psCmd =
+                   (PVRSRV_COMMAND *) ((IMG_UINT32) psQueue->pvLinQueueKM +
+                                       ui32ReadOffset);
+
+               off =
+                   printAppend(buffer, size, off,
+                               "%p %p  %5lu  %6lu  %3lu  %5lu   %2lu   %2lu    %3lu  \n",
+                               psQueue, 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)
+               off = printAppend(buffer, size, off, "%p <empty>\n", psQueue);
+       return off;
+}
+
+off_t QueuePrintQueues(char *buffer, size_t size, off_t off)
+{
+       SYS_DATA *psSysData;
+       PVRSRV_QUEUE_INFO *psQueue;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK)
+               return END_OF_FILE;
+
+       if (!off)
+               return printAppend(buffer, size, 0,
+                                  "Command Queues\n"
+                                  "Queue    CmdPtr      Pid Command Size DevInd  DSC  SSC  #Data ...\n");
+
+       for (psQueue = psSysData->psQueueList; --off && psQueue;
+            psQueue = psQueue->psNextKM) ;
+
+       return psQueue ? QueuePrintCommands(psQueue, buffer,
+                                           size) : END_OF_FILE;
+}
+#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)
+
+IMG_UINT32 NearestPower2(IMG_UINT32 ui32Value)
+{
+       IMG_UINT32 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_UINT32
+                                                        ui32QueueSize,
+                                                        PVRSRV_QUEUE_INFO **
+                                                        ppsQueueInfo)
+{
+       PVRSRV_QUEUE_INFO *psQueueInfo;
+       IMG_UINT32 ui32Power2QueueSize = NearestPower2(ui32QueueSize);
+       SYS_DATA *psSysData;
+       PVRSRV_ERROR eError;
+       IMG_HANDLE hMemBlock;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                      sizeof(PVRSRV_QUEUE_INFO),
+                      (IMG_VOID **) & psQueueInfo, &hMemBlock) != 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();
+
+       if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                      ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
+                      &psQueueInfo->pvLinQueueKM, &hMemBlock) != 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;
+               }
+       }
+
+       if (OSLockResource(&psSysData->sQProcessResource,
+                          KERNEL_ID) != PVRSRV_OK) {
+               goto ErrorExit;
+       }
+
+       psQueueInfo->psNextKM = psSysData->psQueueList;
+       psSysData->psQueueList = psQueueInfo;
+
+       if (OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID) !=
+           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]);
+               }
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                         sizeof(PVRSRV_QUEUE_INFO),
+                         psQueueInfo, psQueueInfo->hMemBlock[0]);
+       }
+
+       return PVRSRV_ERROR_GENERIC;
+}
+
+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;
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       psQueue = psSysData->psQueueList;
+
+       do {
+               if (psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset) {
+                       bTimeout = IMG_FALSE;
+                       break;
+               }
+
+               if (bStart == IMG_FALSE) {
+                       bStart = IMG_TRUE;
+                       uiStart = OSClockus();
+               }
+               OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+       } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+
+       if (bTimeout) {
+
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
+               eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
+       }
+
+       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,
+                         psQueueInfo->ui32QueueSize,
+                         psQueueInfo->pvLinQueueKM, psQueueInfo->hMemBlock[1]);
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                         sizeof(PVRSRV_QUEUE_INFO),
+                         psQueueInfo, psQueueInfo->hMemBlock[0]);
+       } else {
+               while (psQueue) {
+                       if (psQueue->psNextKM == psQueueInfo) {
+                               psQueue->psNextKM = psQueueInfo->psNextKM;
+
+                               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                         psQueueInfo->ui32QueueSize,
+                                         psQueueInfo->pvLinQueueKM,
+                                         psQueueInfo->hMemBlock[1]);
+                               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                         sizeof(PVRSRV_QUEUE_INFO),
+                                         psQueueInfo,
+                                         psQueueInfo->hMemBlock[0]);
+                               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_UINT32 ui32ParamSize,
+                                                   IMG_VOID ** ppvSpace)
+{
+       IMG_BOOL bTimeout = IMG_TRUE;
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0, uiCurrent = 0;
+
+       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;
+       }
+
+       do {
+               if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize) {
+                       bTimeout = IMG_FALSE;
+                       break;
+               }
+
+               if (bStart == IMG_FALSE) {
+                       bStart = IMG_TRUE;
+                       uiStart = OSClockus();
+               }
+               OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+
+               uiCurrent = OSClockus();
+               if (uiCurrent < uiStart) {
+
+                       uiStart = 0;
+               }
+       } while ((uiCurrent - uiStart) < MAX_HW_TIME_US);
+
+       if (bTimeout == IMG_TRUE) {
+               *ppvSpace = IMG_NULL;
+
+               return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+       } else {
+               *ppvSpace =
+                   (IMG_VOID *) (psQueue->ui32WriteOffset +
+                                 (IMG_UINT32) psQueue->pvLinQueueUM);
+       }
+
+       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_UINT32 ui32DataByteSize)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_COMMAND *psCommand;
+       IMG_UINT32 ui32CommandSize;
+       IMG_UINT32 i;
+
+       ui32DataByteSize = (ui32DataByteSize + 3) & 0xFFFFFFFC;
+
+       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_UINT8 *) psCommand) +
+                                   sizeof(PVRSRV_COMMAND));
+
+       psCommand->psSrcSync =
+           (PVRSRV_SYNC_OBJECT *) (((IMG_UINT8 *) psCommand->psDstSync)
+                                   +
+                                   (ui32DstSyncCount *
+                                    sizeof(PVRSRV_SYNC_OBJECT)));
+
+       psCommand->pvData =
+           (PVRSRV_SYNC_OBJECT *) (((IMG_UINT8 *) 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);
+       }
+
+       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);
+       }
+
+       *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_UINT8 *) psQueue->pvLinQueueKM)
+                        + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND));
+       }
+
+       if (psCommand->ui32SrcSyncCount > 0) {
+               psCommand->psSrcSync =
+                   (PVRSRV_SYNC_OBJECT
+                    *) (((IMG_UINT8 *) psQueue->pvLinQueueKM)
+                        + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+                        +
+                        (psCommand->ui32DstSyncCount *
+                         sizeof(PVRSRV_SYNC_OBJECT)));
+       }
+
+       psCommand->pvData =
+           (PVRSRV_SYNC_OBJECT *) (((IMG_UINT8 *) 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;
+}
+
+IMG_EXPORT
+    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;
+
+       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",
+                                        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;
+       }
+
+       psCmdCompleteData =
+           psSysData->ppsCmdCompleteData[psCommand->ui32DevIndex][psCommand->
+                                                                  CommandType];
+       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];
+       }
+
+       psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+       for (i = 0; i < psCommand->ui32SrcSyncCount; i++) {
+               psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+       }
+
+       if (psSysData->
+           ppfnCmdProcList[psCommand->ui32DevIndex][psCommand->
+                                                    CommandType] ((IMG_HANDLE)
+                                                                  psCmdCompleteData,
+                                                                  psCommand->
+                                                                  ui32DataSize,
+                                                                  psCommand->
+                                                                  pvData) ==
+           IMG_FALSE) {
+
+               psCmdCompleteData->bInUse = IMG_FALSE;
+               eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+       }
+
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVProcessQueues(IMG_UINT32 ui32CallerID, IMG_BOOL bFlush)
+{
+       PVRSRV_QUEUE_INFO *psQueue;
+       SYS_DATA *psSysData;
+       PVRSRV_COMMAND *psCommand;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       PVRSRV_ERROR eError;
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       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_UINT32) psQueue->
+                                               pvLinQueueKM +
+                                               psQueue->ui32ReadOffset);
+
+                       if (PVRSRVProcessCommand(psSysData, psCommand, bFlush)
+                           == PVRSRV_OK) {
+
+                               UPDATE_QUEUE_ROFF(psQueue,
+                                                 psCommand->ui32CmdSize)
+
+                                   if (bFlush) {
+                                       continue;
+                               }
+                       }
+
+                       break;
+               }
+               psQueue = psQueue->psNextKM;
+       }
+
+       if (bFlush) {
+               PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       while (psDeviceNode != IMG_NULL) {
+               if (psDeviceNode->bReProcessDeviceCommandComplete &&
+                   psDeviceNode->pfnDeviceCommandComplete != IMG_NULL) {
+                       (*psDeviceNode->
+                        pfnDeviceCommandComplete) (psDeviceNode);
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+
+       OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID);
+
+       if (psSysData->bReProcessQueues) {
+               return PVRSRV_ERROR_PROCESSING_BLOCKED;
+       }
+
+       return PVRSRV_OK;
+}
+
+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;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               return;
+       }
+
+       for (i = 0; i < psCmdCompleteData->ui32DstSyncCount; i++) {
+               psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->
+                   ui32WriteOpsComplete++;
+       }
+
+       for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount; i++) {
+               psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->
+                   ui32ReadOpsComplete++;
+       }
+
+       psCmdCompleteData->bInUse = IMG_FALSE;
+
+       PVRSRVCommandCompleteCallbacks();
+
+#if defined(SYS_USING_INTERRUPTS)
+       if (bScheduleMISR) {
+               OSScheduleMISR(psSysData);
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
+#endif
+}
+
+IMG_VOID PVRSRVCommandCompleteCallbacks(IMG_VOID)
+{
+       SYS_DATA *psSysData;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVCommandCompleteCallbacks: SysAcquireData failed"));
+               return;
+       }
+
+       psDeviceNode = psSysData->psDeviceNodeList;
+       while (psDeviceNode != IMG_NULL) {
+               if (psDeviceNode->pfnDeviceCommandComplete != IMG_NULL) {
+
+                       (*psDeviceNode->
+                        pfnDeviceCommandComplete) (psDeviceNode);
+               }
+               psDeviceNode = psDeviceNode->psNext;
+       }
+}
+
+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 i;
+       IMG_UINT32 ui32AllocSize;
+       PFN_CMD_PROC *ppfnCmdProc;
+       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;
+       }
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRegisterCmdProcListKM: SysAcquireData failed"));
+               return eError;
+       }
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                           ui32CmdCount * sizeof(PFN_CMD_PROC),
+                           (IMG_VOID **) & psSysData->
+                           ppfnCmdProcList[ui32DevIndex], IMG_NULL);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRegisterCmdProcListKM: Failed to alloc queue"));
+               return eError;
+       }
+
+       ppfnCmdProc = psSysData->ppfnCmdProcList[ui32DevIndex];
+
+       for (i = 0; i < ui32CmdCount; i++) {
+               ppfnCmdProc[i] = ppfnCmdProcList[i];
+       }
+
+       ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA *);
+       eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                           ui32AllocSize,
+                           (IMG_VOID **) & psSysData->
+                           ppsCmdCompleteData[ui32DevIndex], IMG_NULL);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
+               goto ErrorExit;
+       }
+
+       for (i = 0; i < ui32CmdCount; i++) {
+
+               ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+                   + ((ui32MaxSyncsPerCmd[i][0]
+                       + ui32MaxSyncsPerCmd[i][1])
+                      * sizeof(PVRSRV_SYNC_OBJECT));
+
+               eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                                   ui32AllocSize,
+                                   (IMG_VOID **) & psSysData->
+                                   ppsCmdCompleteData[ui32DevIndex][i],
+                                   IMG_NULL);
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d",
+                                i));
+                       goto ErrorExit;
+               }
+
+               OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex][i], 0x00,
+                        ui32AllocSize);
+
+               psCmdCompleteData =
+                   psSysData->ppsCmdCompleteData[ui32DevIndex][i];
+
+               psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT *)
+                   (((IMG_UINT32) psCmdCompleteData)
+                    + sizeof(COMMAND_COMPLETE_DATA));
+               psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT *)
+                   (((IMG_UINT32) psCmdCompleteData->psDstSync)
+                    + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0]));
+       }
+
+       return PVRSRV_OK;
+
+ErrorExit:
+
+       if (psSysData->ppsCmdCompleteData[ui32DevIndex] != IMG_NULL) {
+               for (i = 0; i < ui32CmdCount; i++) {
+                       if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] !=
+                           IMG_NULL) {
+                               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+                                         psSysData->
+                                         ppsCmdCompleteData[ui32DevIndex][i],
+                                         IMG_NULL);
+                       }
+               }
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+                         psSysData->ppsCmdCompleteData[ui32DevIndex],
+                         IMG_NULL);
+       }
+
+       if (psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL) {
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+                         psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL);
+       }
+
+       return eError;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+                                          IMG_UINT32 ui32CmdCount)
+{
+       SYS_DATA *psSysData;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 i;
+
+       if (ui32DevIndex >= SYS_DEVICE_COUNT) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+                        ui32DevIndex));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = SysAcquireData(&psSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRemoveCmdProcListKM: SysAcquireData failed"));
+               return eError;
+       }
+
+       if (psSysData->ppsCmdCompleteData[ui32DevIndex] != IMG_NULL) {
+               for (i = 0; i < ui32CmdCount; i++) {
+
+                       if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] !=
+                           IMG_NULL) {
+                               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+                                         psSysData->
+                                         ppsCmdCompleteData[ui32DevIndex][i],
+                                         IMG_NULL);
+                       }
+               }
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+                         psSysData->ppsCmdCompleteData[ui32DevIndex],
+                         IMG_NULL);
+       }
+
+       if (psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL) {
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+                         psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL);
+       }
+
+       return PVRSRV_OK;
+}
diff --git a/pvr/queue.h b/pvr/queue.h
new file mode 100644 (file)
index 0000000..687b36b
--- /dev/null
@@ -0,0 +1,124 @@
+/**********************************************************************
+ *
+ * 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;
+       } COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
+
+#if !defined(USE_CODE)
+
+        IMG_IMPORT
+           PVRSRV_ERROR PVRSRVProcessQueues(IMG_UINT32 ui32CallerID,
+                                            IMG_BOOL bFlush);
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/types.h>
+        off_t QueuePrintQueues(char *buffer, size_t size, off_t off);
+#endif
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_UINT32
+                                                                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_UINT32
+                                                           ui32DataByteSize);
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *
+                                                           psQueue,
+                                                           IMG_UINT32
+                                                           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_VOID PVRSRVCommandCompleteCallbacks(IMG_VOID);
+
+        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/pvr/ra.c b/pvr/ra.c
new file mode 100644 (file)
index 0000000..e7253bf
--- /dev/null
+++ b/pvr/ra.c
@@ -0,0 +1,1181 @@
+/**********************************************************************
+ *
+ * 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)
+
+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;
+};
+typedef struct _BT_ BT;
+
+struct _RA_ARENA_ {
+
+       char *name;
+
+       IMG_UINT32 uQuantum;
+
+        IMG_BOOL(*pImportAlloc) (void *,
+                                 IMG_SIZE_T uSize,
+                                 IMG_SIZE_T * pActualSize,
+                                 BM_MAPPING ** ppsMapping,
+                                 IMG_UINT32 uFlags, IMG_UINTPTR_T * pBase);
+       void (*pImportFree) (void *, IMG_UINTPTR_T, BM_MAPPING * psMapping);
+       void (*pBackingStoreFree) (void *, IMG_UINT32, IMG_UINT32, IMG_HANDLE);
+
+       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
+       char szProcInfoName[PROC_NAME_SIZE];
+       char szProcSegsName[PROC_NAME_SIZE];
+#endif
+};
+
+void RA_Dump(RA_ARENA * pArena);
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static int
+RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
+           void *data);
+static int RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
+                      void *data);
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+void CheckBMFreespace(void);
+#endif
+
+static IMG_BOOL
+_RequestAllocFail(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 void
+_SegmentListInsertAfter(RA_ARENA * pArena, BT * pInsertionPoint, BT * pBT)
+{
+       PVR_ASSERT(pArena != IMG_NULL);
+       PVR_ASSERT(pInsertionPoint != IMG_NULL);
+
+       pBT->pNextSegment = pInsertionPoint->pNextSegment;
+       pBT->pPrevSegment = pInsertionPoint;
+       if (pInsertionPoint->pNextSegment == IMG_NULL)
+               pArena->pTailSegment = pBT;
+       else
+               pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+       pInsertionPoint->pNextSegment = pBT;
+}
+
+static void _SegmentListInsert(RA_ARENA * pArena, BT * pBT)
+{
+
+       if (pArena->pHeadSegment == IMG_NULL) {
+               pArena->pHeadSegment = pArena->pTailSegment = pBT;
+               pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
+       } else {
+               BT *pBTScan;
+               pBTScan = pArena->pHeadSegment;
+               while (pBTScan->pNextSegment != IMG_NULL
+                      && pBT->base >= pBTScan->pNextSegment->base)
+                       pBTScan = pBTScan->pNextSegment;
+               _SegmentListInsertAfter(pArena, pBTScan, pBT);
+       }
+}
+
+static 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 (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(BT),
+                      (IMG_VOID **) & pNeighbour, IMG_NULL) != PVRSRV_OK) {
+               return IMG_NULL;
+       }
+
+       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;
+       return pNeighbour;
+}
+
+static 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 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) != PVRSRV_OK) {
+               return IMG_NULL;
+       }
+
+       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) != PVRSRV_OK) {
+               return IMG_NULL;
+       }
+
+       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);
+       pBT = _BuildBT(base, uSize);
+       if (pBT != IMG_NULL) {
+               _SegmentListInsert(pArena, pBT);
+               _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)
+{
+       BT *pSpanStart;
+       BT *pSpanEnd;
+       BT *pBT;
+
+       PVR_ASSERT(pArena != 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;
+       }
+       pSpanEnd = _BuildSpanMarker(base + uSize, 0);
+       if (pSpanEnd == IMG_NULL) {
+               goto fail_end;
+       }
+
+       pBT = _BuildBT(base, uSize);
+       if (pBT == IMG_NULL) {
+               goto fail_bt;
+       }
+
+       _SegmentListInsert(pArena, pSpanStart);
+       _SegmentListInsertAfter(pArena, pSpanStart, pBT);
+       _FreeListInsert(pArena, pBT);
+       _SegmentListInsertAfter(pArena, pBT, pSpanEnd);
+#ifdef RA_STATS
+       pArena->sStatistics.uTotalResourceCount += uSize;
+#endif
+       return pBT;
+
+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 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);
+
+#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,
+                                                 uRoundedStart, 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);
+
+       PVR_UNREFERENCED_PARAMETER(uFlags);
+
+       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,
+                                                            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 (!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(*alloc) (IMG_VOID *, IMG_SIZE_T uSize,
+                                     IMG_SIZE_T * pActualSize,
+                                     BM_MAPPING ** ppsMapping,
+                                     IMG_UINT32 _flags, IMG_UINTPTR_T * pBase),
+                   IMG_VOID(*free) (IMG_VOID *, IMG_UINTPTR_T,
+                                    BM_MAPPING * psMapping),
+                   IMG_VOID(*backingstore_free) (IMG_VOID *, IMG_UINT32,
+                                                 IMG_UINT32, IMG_HANDLE),
+                   IMG_VOID * pImportHandle)
+{
+       RA_ARENA *pArena;
+       BT *pBT;
+       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, alloc, free));
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(*pArena),
+                      (IMG_VOID **) & pArena, IMG_NULL) != PVRSRV_OK) {
+               goto arena_fail;
+       }
+
+       pArena->name = name;
+       pArena->pImportAlloc = alloc != IMG_NULL ? alloc : _RequestAllocFail;
+       pArena->pImportFree = 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) {
+               sprintf(pArena->szProcInfoName, "ra_info_%s", pArena->name);
+               CreateProcEntry(pArena->szProcInfoName, RA_DumpInfo, 0, pArena);
+               sprintf(pArena->szProcSegsName, "ra_segs_%s", pArena->name);
+               CreateProcEntry(pArena->szProcSegsName, RA_DumpSegs, 0, pArena);
+       }
+#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, 0, pArena, IMG_NULL);
+arena_fail:
+       return IMG_NULL;
+}
+
+void RA_Delete(RA_ARENA * pArena)
+{
+       IMG_UINT32 uIndex;
+
+       PVR_ASSERT(pArena != IMG_NULL);
+       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;
+               PVR_ASSERT(pBT->type == btt_free);
+               _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)
+       RemoveProcEntry(pArena->szProcInfoName);
+       RemoveProcEntry(pArena->szProcSegsName);
+#endif
+       HASH_Delete(pArena->pSegmentHash);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pArena, IMG_NULL);
+}
+
+IMG_BOOL RA_Add(RA_ARENA * pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+       PVR_ASSERT(pArena != IMG_NULL);
+
+       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_FALSE;
+       IMG_SIZE_T uSize = uRequestSize;
+
+       PVR_ASSERT(pArena != IMG_NULL);
+
+#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));
+
+       return bResult;
+}
+
+void RA_Free(RA_ARENA * pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
+{
+       BT *pBT;
+
+       PVR_ASSERT(pArena != IMG_NULL);
+
+#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
+               {
+                       unsigned char *p;
+                       unsigned char *endp;
+
+                       p = (unsigned char *)pBT->base +
+                           SysGetDevicePhysOffset();
+                       endp = (unsigned char *)((IMG_UINT32) (p + pBT->uSize));
+                       while ((IMG_UINT32) p & 3) {
+                               *p++ = 0xAA;
+                       }
+                       while (p <
+                              (unsigned char *)((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)",
+                                (unsigned char *)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) - 1;
+
+       return IMG_FALSE;
+}
+
+#ifdef USE_BM_FREESPACE_CHECK
+RA_ARENA *pJFSavedArena = IMG_NULL;
+
+void CheckBMFreespace(void)
+{
+       BT *pBT;
+       unsigned char *p;
+       unsigned char *endp;
+
+       if (pJFSavedArena != IMG_NULL) {
+               for (pBT = pJFSavedArena->pHeadSegment; pBT != IMG_NULL;
+                    pBT = pBT->pNextSegment) {
+                       if (pBT->type == btt_free) {
+                               p = (unsigned char *)pBT->base +
+                                   SysGetDevicePhysOffset();
+                               endp =
+                                   (unsigned char
+                                    *)((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, *(unsigned long *)p);
+                                               for (;;) ;
+                                               break;
+                                       }
+                               }
+                               while (p < endp) {
+                                       if (*(unsigned long *)p != 0xAAAAAAAA) {
+                                               fprintf(stderr,
+                                                       "BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",
+                                                       p, *(unsigned long *)p);
+                                               for (;;) ;
+                                               break;
+                                       }
+                                       p += 4;
+                               }
+                       }
+               }
+       }
+}
+#endif
+
+#if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS)
+static char *_BTType(int eType)
+{
+       switch (eType) {
+       case btt_span:
+               return "span";
+       case btt_free:
+               return "free";
+       case btt_live:
+               return "live";
+       }
+       return "junk";
+}
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static int
+RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
+           void *data)
+{
+       BT *pBT = 0;
+       int len = 0;
+       RA_ARENA *pArena = (RA_ARENA *) data;
+
+       if (count < 80) {
+               *start = (char *)0;
+               return (0);
+       }
+       *eof = 0;
+       *start = (char *)1;
+       if (off == 0) {
+               return printAppend(page, count, 0,
+                                  "Arena \"%s\"\nBase         Size Type Ref\n",
+                                  pArena->name);
+       }
+       for (pBT = pArena->pHeadSegment; --off && pBT;
+            pBT = pBT->pNextSegment) ;
+       if (pBT) {
+               len = printAppend(page, count, 0, "%08x %8x %4s %08x\n",
+                                 (unsigned int)pBT->base,
+                                 (unsigned int)pBT->uSize, _BTType(pBT->type),
+                                 (unsigned int)pBT->psMapping);
+       } else {
+               *eof = 1;
+       }
+       return (len);
+}
+
+static int
+RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
+           void *data)
+{
+       int len = 0;
+       RA_ARENA *pArena = (RA_ARENA *) data;
+
+       if (count < 80) {
+               *start = (char *)0;
+               return (0);
+       }
+       *eof = 0;
+       switch (off) {
+       case 0:
+               len =
+                   printAppend(page, count, 0, "quantum\t\t\t%lu\n",
+                               pArena->uQuantum);
+               break;
+       case 1:
+               len =
+                   printAppend(page, count, 0, "import_handle\t\t%08X\n",
+                               (unsigned int)pArena->pImportHandle);
+               break;
+#ifdef RA_STATS
+       case 2:
+               len =
+                   printAppend(page, count, 0, "span count\t\t%lu\n",
+                               pArena->sStatistics.uSpanCount);
+               break;
+       case 3:
+               len =
+                   printAppend(page, count, 0, "live segment count\t%lu\n",
+                               pArena->sStatistics.uLiveSegmentCount);
+               break;
+       case 4:
+               len =
+                   printAppend(page, count, 0, "free segment count\t%lu\n",
+                               pArena->sStatistics.uFreeSegmentCount);
+               break;
+       case 5:
+               len =
+                   printAppend(page, count, 0,
+                               "free resource count\t%lu (0x%x)\n",
+                               pArena->sStatistics.uFreeResourceCount,
+                               (unsigned int)pArena->sStatistics.
+                               uFreeResourceCount);
+               break;
+       case 6:
+               len =
+                   printAppend(page, count, 0, "total allocs\t\t%lu\n",
+                               pArena->sStatistics.uCumulativeAllocs);
+               break;
+       case 7:
+               len =
+                   printAppend(page, count, 0, "total frees\t\t%lu\n",
+                               pArena->sStatistics.uCumulativeFrees);
+               break;
+       case 8:
+               len =
+                   printAppend(page, count, 0, "import count\t\t%lu\n",
+                               pArena->sStatistics.uImportCount);
+               break;
+       case 9:
+               len =
+                   printAppend(page, count, 0, "export count\t\t%lu\n",
+                               pArena->sStatistics.uExportCount);
+               break;
+#endif
+
+       default:
+               *eof = 1;
+       }
+       *start = (char *)1;
+       return (len);
+}
+#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=%08X freeCB=%08X handle=%08X 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%lu\n",
+                      pArena->sStatistics.uSpanCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count =
+           OSSNPrintf(pszStr, 100, "live segment count\t%lu\n",
+                      pArena->sStatistics.uLiveSegmentCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count =
+           OSSNPrintf(pszStr, 100, "free segment count\t%lu\n",
+                      pArena->sStatistics.uFreeSegmentCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%lu (0x%x)\n",
+                             pArena->sStatistics.uFreeResourceCount,
+                             (unsigned int)pArena->sStatistics.
+                             uFreeResourceCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count =
+           OSSNPrintf(pszStr, 100, "total allocs\t\t%lu\n",
+                      pArena->sStatistics.uCumulativeAllocs);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count =
+           OSSNPrintf(pszStr, 100, "total frees\t\t%lu\n",
+                      pArena->sStatistics.uCumulativeFrees);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count =
+           OSSNPrintf(pszStr, 100, "import count\t\t%lu\n",
+                      pArena->sStatistics.uImportCount);
+       UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+       CHECK_SPACE(ui32StrLen);
+       i32Count =
+           OSSNPrintf(pszStr, 100, "export count\t\t%lu\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=%08X\n",
+                              (unsigned long)pBT->base, pBT->uSize,
+                              _BTType(pBT->type), pBT->psMapping);
+               UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+       }
+
+       *ppszStr = pszStr;
+       *pui32StrLen = ui32StrLen;
+
+       return PVRSRV_OK;
+}
+#endif
diff --git a/pvr/ra.h b/pvr/ra.h
new file mode 100644 (file)
index 0000000..432fdde
--- /dev/null
+++ b/pvr/ra.h
@@ -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 _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_UINT32 uSpanCount;
+
+       IMG_UINT32 uLiveSegmentCount;
+
+       IMG_UINT32 uFreeSegmentCount;
+
+       IMG_UINT32 uTotalResourceCount;
+
+       IMG_UINT32 uFreeResourceCount;
+
+       IMG_UINT32 uCumulativeAllocs;
+
+       IMG_UINT32 uCumulativeFrees;
+
+       IMG_UINT32 uImportCount;
+
+       IMG_UINT32 uExportCount;
+};
+typedef struct _RA_STATISTICS_ RA_STATISTICS;
+
+struct _RA_SEGMENT_DETAILS_ {
+       IMG_UINT32 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(*alloc) (IMG_VOID * _h,
+                                     IMG_SIZE_T uSize,
+                                     IMG_SIZE_T * pActualSize,
+                                     BM_MAPPING ** ppsMapping,
+                                     IMG_UINT32 uFlags,
+                                     IMG_UINTPTR_T * pBase),
+                   IMG_VOID(*free) (IMG_VOID *,
+                                    IMG_UINTPTR_T,
+                                    BM_MAPPING * psMapping),
+                   IMG_VOID(*backingstore_free) (IMG_VOID *,
+                                                 IMG_UINT32,
+                                                 IMG_UINT32,
+                                                 IMG_HANDLE),
+                   IMG_VOID * import_handle);
+
+void RA_Delete(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);
+
+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);
+
+#endif
+
+#endif
diff --git a/pvr/regpaths.h b/pvr/regpaths.h
new file mode 100644 (file)
index 0000000..29bf9f1
--- /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 
+ *
+ ******************************************************************************/
+
+#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/pvr/resman.c b/pvr/resman.c
new file mode 100644 (file)
index 0000000..d503b0e
--- /dev/null
@@ -0,0 +1,606 @@
+/**********************************************************************
+ *
+ * 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__
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#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 DECLARE_MUTEX(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;
+
+#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) != 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);
+       }
+}
+
+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);
+       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;
+
+       psResManContext->psNext = gpsResList->psContextList;
+       psResManContext->ppsThis = &gpsResList->psContextList;
+       gpsResList->psContextList = psResManContext;
+       if (psResManContext->psNext) {
+               psResManContext->psNext->ppsThis = &(psResManContext->psNext);
+       }
+
+       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);
+
+               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, 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_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);
+       }
+
+       PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
+
+       *(psResManContext->ppsThis) = psResManContext->psNext;
+       if (psResManContext->psNext) {
+               psResManContext->psNext->ppsThis = psResManContext->ppsThis;
+       }
+
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, 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);
+
+       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",
+                psResManContext, ui32ResType, (IMG_UINT32) pvParam,
+                ui32Param, pfnFreeResource));
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(RESMAN_ITEM), (IMG_VOID **) & psNewResItem,
+                      IMG_NULL) != 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;
+
+       psNewResItem->ppsThis = &psResManContext->psResItemList;
+       psNewResItem->psNext = psResManContext->psResItemList;
+       psResManContext->psResItemList = psNewResItem;
+       if (psNewResItem->psNext) {
+               psNewResItem->psNext->ppsThis = &psNewResItem->psNext;
+       }
+
+       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", 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",
+                psResManContext, ui32SearchCriteria, ui32ResType,
+                (IMG_UINT32) pvParam, ui32Param));
+
+       eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+                                       ui32ResType, pvParam, ui32Param,
+                                       IMG_TRUE);
+
+       VALIDATERESLIST();
+
+       RELEASE_SYNC_OBJ;
+
+       return eError;
+}
+
+IMG_VOID ResManDissociateRes(RESMAN_ITEM * psResItem,
+                            PRESMAN_CONTEXT psNewResManContext)
+{
+       PVR_ASSERT(psResItem != IMG_NULL);
+       PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+
+       if (psNewResManContext != IMG_NULL) {
+
+               if (psResItem->psNext) {
+                       psResItem->psNext->ppsThis = psResItem->ppsThis;
+               }
+               *psResItem->ppsThis = psResItem->psNext;
+
+               psResItem->ppsThis = &psNewResManContext->psResItemList;
+               psResItem->psNext = psNewResManContext->psResItemList;
+               psNewResManContext->psResItemList = psResItem;
+               if (psResItem->psNext) {
+                       psResItem->psNext->ppsThis = &psResItem->psNext;
+               }
+       } else {
+               FreeResourceByPtr(psResItem, IMG_FALSE);
+       }
+}
+
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT
+                                                 psResManContext,
+                                                 RESMAN_ITEM * psItem)
+{
+       RESMAN_ITEM *psCurItem;
+
+       PVR_ASSERT(psResManContext != IMG_NULL);
+       PVR_ASSERT(psItem != IMG_NULL);
+       PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+
+       ACQUIRE_SYNC_OBJ;
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+                psItem, 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",
+                psResManContext,
+                psItem->ui32ResType, (IMG_UINT32) psItem->pvParam,
+                psItem->ui32Param, psItem->pfnFreeResource,
+                psItem->ui32Flags));
+
+       psCurItem = psResManContext->psResItemList;
+
+       while (psCurItem != IMG_NULL) {
+
+               if (psCurItem != psItem) {
+
+                       psCurItem = psCurItem->psNext;
+               } else {
+
+                       RELEASE_SYNC_OBJ;
+                       return PVRSRV_OK;
+               }
+       }
+
+       RELEASE_SYNC_OBJ;
+
+       return PVRSRV_ERROR_NOT_OWNER;
+}
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM * psItem,
+                                     IMG_BOOL bExecuteCallback)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       PVR_ASSERT(psItem != IMG_NULL);
+       PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+                psItem, 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_UINT32) psItem->pvParam,
+                psItem->ui32Param, psItem->pfnFreeResource,
+                psItem->ui32Flags));
+
+       if (psItem->psNext) {
+               psItem->psNext->ppsThis = psItem->ppsThis;
+       }
+       *psItem->ppsThis = psItem->psNext;
+
+       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;
+
+       if (OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psItem, IMG_NULL) !=
+           PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "FreeResourceByPtr: ERROR freeing resource list item memory"));
+               eError = PVRSRV_ERROR_GENERIC;
+       }
+
+       return (eError);
+}
+
+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;
+       IMG_BOOL bMatch;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       psCurItem = psResManContext->psResItemList;
+
+       while (psCurItem != IMG_NULL) {
+
+               bMatch = IMG_TRUE;
+
+               if ((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) &&
+                   psCurItem->ui32ResType != ui32ResType) {
+                       bMatch = IMG_FALSE;
+               }
+
+               else if ((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) &&
+                        psCurItem->pvParam != pvParam) {
+                       bMatch = IMG_FALSE;
+               }
+
+               else if ((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) &&
+                        psCurItem->ui32Param != ui32Param) {
+                       bMatch = IMG_FALSE;
+               }
+
+               if (!bMatch) {
+
+                       psCurItem = psCurItem->psNext;
+               } else {
+
+                       eError = FreeResourceByPtr(psCurItem, bExecuteCallback);
+
+                       if (eError != PVRSRV_OK) {
+                               return eError;
+                       }
+
+                       psCurItem = psResManContext->psResItemList;
+               }
+       }
+
+       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",
+                                psCurContext, psCurContext->ppsThis,
+                                psCurContext->psNext, 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",
+                                        psCurItem, psCurItem->ppsThis,
+                                        psCurItem->psNext, ppsThisItem));
+                               PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+                       }
+
+                       ppsThisItem = &psCurItem->psNext;
+                       psCurItem = psCurItem->psNext;
+               }
+
+               ppsThisContext = &psCurContext->psNext;
+               psCurContext = psCurContext->psNext;
+       }
+}
+#endif
diff --git a/pvr/resman.h b/pvr/resman.h
new file mode 100644 (file)
index 0000000..1078f64
--- /dev/null
@@ -0,0 +1,103 @@
+/**********************************************************************
+ *
+ * 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
+
+       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,
+               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_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);
+
+       IMG_VOID 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);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/services.h b/pvr/services.h
new file mode 100644 (file)
index 0000000..8e10c83
--- /dev/null
@@ -0,0 +1,994 @@
+/**********************************************************************
+ *
+ * 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 IMG_CONST const
+
+#define PVRSRV_MAX_CMD_SIZE            1024
+
+#define PVRSRV_MAX_DEVICES             16
+
+#define EVENTOBJNAME_MAXLENGTH (50)
+
+#define PVRSRV_MEM_READ                                                (1UL<<0)
+#define PVRSRV_MEM_WRITE                                       (1UL<<1)
+#define PVRSRV_MEM_CACHE_CONSISTENT                    (1UL<<2)
+#define PVRSRV_MEM_NO_SYNCOBJ                          (1UL<<3)
+#define PVRSRV_MEM_INTERLEAVED                         (1UL<<4)
+#define PVRSRV_MEM_DUMMY                                       (1UL<<5)
+#define PVRSRV_MEM_EDM_PROTECT                         (1UL<<6)
+#define PVRSRV_MEM_ZERO                                                (1UL<<7)
+#define PVRSRV_MEM_USER_SUPPLIED_DEVVADDR      (1UL<<8)
+#define PVRSRV_MEM_RAM_BACKED_ALLOCATION       (1UL<<9)
+#define PVRSRV_MEM_NO_RESMAN                           (1UL<<10)
+
+#define PVRSRV_HAP_CACHED                                      (1UL<<12)
+#define PVRSRV_HAP_UNCACHED                                    (1UL<<13)
+#define PVRSRV_HAP_WRITECOMBINE                                (1UL<<14)
+#define PVRSRV_HAP_CACHETYPE_MASK                      (PVRSRV_HAP_CACHED|PVRSRV_HAP_UNCACHED|PVRSRV_HAP_WRITECOMBINE)
+#define PVRSRV_HAP_KERNEL_ONLY                         (1UL<<15)
+#define PVRSRV_HAP_SINGLE_PROCESS                      (1UL<<16)
+#define PVRSRV_HAP_MULTI_PROCESS                       (1UL<<17)
+#define PVRSRV_HAP_FROM_EXISTING_PROCESS       (1UL<<18)
+#define PVRSRV_HAP_NO_CPU_VIRTUAL                      (1UL<<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_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                         (1UL<<0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT                     (1UL<<1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT                      (1UL<<2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT     (1UL<<3)
+
+#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
+
+       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_EXT = 8,
+
+               PVRSRV_DEVICE_TYPE_LAST = 8,
+
+               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 )
+
+       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
+       } 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_CONNECTION_ {
+               IMG_HANDLE hServices;
+               IMG_UINT32 ui32ProcessID;
+       } PVRSRV_CONNECTION;
+
+       typedef struct _PVRSRV_DEV_DATA_ {
+               PVRSRV_CONNECTION sConnection;
+               IMG_HANDLE hDevCookie;
+
+       } PVRSRV_DEV_DATA, *PPVRSRV_DEV_DATA;
+
+       typedef struct _PVRSRV_MEMUPDATE_ {
+               IMG_UINT32 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_UINT32 ui32AllocSize;
+
+               struct _PVRSRV_CLIENT_SYNC_INFO_ *psClientSyncInfo;
+
+               IMG_HANDLE hMappingInfo;
+
+               IMG_HANDLE hKernelMemInfo;
+
+               IMG_HANDLE hResItem;
+
+               struct _PVRSRV_CLIENT_MEM_INFO_ *psNext;
+
+       } PVRSRV_CLIENT_MEM_INFO, *PPVRSRV_CLIENT_MEM_INFO;
+
+#if 0
+       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;
+#endif
+
+#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;
+       } PVRSRV_HEAP_INFO;
+
+       typedef struct _PVRSRV_DEVICE_IDENTIFIER_ {
+               PVRSRV_DEVICE_TYPE eDeviceType;
+               PVRSRV_DEVICE_CLASS eDeviceClass;
+               IMG_UINT32 ui32DeviceIndex;
+
+       } PVRSRV_DEVICE_IDENTIFIER;
+
+       typedef struct _PVRSRV_EVENTOBJECT_ {
+
+               IMG_CHAR szName[EVENTOBJNAME_MAXLENGTH];
+
+               IMG_HANDLE hOSEventKM;
+
+       } PVRSRV_EVENTOBJECT;
+
+       typedef struct _PVRSRV_MISC_INFO_ {
+               IMG_UINT32 ui32StateRequest;
+               IMG_UINT32 ui32StatePresent;
+
+               IMG_VOID *pvSOCTimerRegisterKM;
+               IMG_VOID *pvSOCTimerRegisterUM;
+               IMG_HANDLE hSOCTimerRegisterOSMemHandle;
+
+               IMG_VOID *pvSOCClockGateRegs;
+               IMG_UINT32 ui32SOCClockGateRegsSize;
+
+               IMG_CHAR *pszMemoryStr;
+               IMG_UINT32 ui32MemoryStrLen;
+
+               PVRSRV_EVENTOBJECT sGlobalEventObject;
+               IMG_HANDLE hOSGlobalEvent;
+
+       } PVRSRV_MISC_INFO;
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION *
+                                                   psConnection);
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVDisconnect(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(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);
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVMapMemInfoToUser(IMG_CONST
+                                                            PVRSRV_DEV_DATA *
+                                                            psDevData,
+                                                            PVRSRV_CLIENT_MEM_INFO
+                                                            * psMemInfo,
+                                                            IMG_VOID *
+                                                            ppvUserLinAddr,
+                                                            IMG_HANDLE *
+                                                            phUserMappingInfo);
+
+       PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapMemInfoFromUser(IMG_CONST
+                                                            PVRSRV_DEV_DATA *
+                                                            psDevData,
+                                                            PVRSRV_CLIENT_MEM_INFO
+                                                            * psMemInfo,
+                                                            IMG_PVOID
+                                                            pvUserLinAddr,
+                                                            IMG_HANDLE
+                                                            hUserMappingInfo);
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem(IMG_CONST
+                                                          PVRSRV_DEV_DATA *
+                                                          psDevData,
+                                                          IMG_HANDLE
+                                                          hDevMemHeap,
+                                                          IMG_UINT32
+                                                          ui32Attribs,
+                                                          IMG_UINT32 ui32Size,
+                                                          IMG_UINT32
+                                                          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 PVRSRVReserveDeviceVirtualMem(IMG_CONST
+                                                                   PVRSRV_DEV_DATA
+                                                                   * psDevData,
+                                                                   IMG_HANDLE
+                                                                   hDevMemHeap,
+                                                                   IMG_DEV_VIRTADDR
+                                                                   *
+                                                                   psDevVAddr,
+                                                                   IMG_UINT32
+                                                                   ui32Size,
+                                                                   IMG_UINT32
+                                                                   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,
+                                                           PVRSRV_CLIENT_MEM_INFO
+                                                           * psSrcMemInfo,
+                                                           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_UINT32
+                                                         ui32ByteSize,
+                                                         IMG_UINT32
+                                                         ui32PageOffset,
+                                                         IMG_BOOL bPhysContig,
+                                                         IMG_SYS_PHYADDR *
+                                                         psSysPAddr,
+                                                         IMG_VOID * pvLinAddr,
+                                                         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
+                                                                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 PVRSRVPDumpMemPol(IMG_CONST
+                                                       PVRSRV_CONNECTION *
+                                                       psConnection,
+                                                       PVRSRV_CLIENT_MEM_INFO *
+                                                       psMemInfo,
+                                                       IMG_UINT32 ui32Offset,
+                                                       IMG_UINT32 ui32Value,
+                                                       IMG_UINT32 ui32Mask,
+                                                       IMG_BOOL bLastFrame,
+                                                       IMG_BOOL bOverwrite);
+
+        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_CONNECTION
+                                                    * psConnection,
+                                                    IMG_UINT32 ui32RegAddr,
+                                                    IMG_UINT32 ui32RegValue,
+                                                    IMG_UINT32 ui32Flags);
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPolWithFlags(IMG_CONST
+                                                                PVRSRV_CONNECTION
+                                                                * psConnection,
+                                                                IMG_UINT32
+                                                                ui32RegAddr,
+                                                                IMG_UINT32
+                                                                ui32RegValue,
+                                                                IMG_UINT32
+                                                                ui32Mask,
+                                                                IMG_UINT32
+                                                                ui32Flags);
+        IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPol(IMG_CONST
+                                                               PVRSRV_CONNECTION
+                                                               * psConnection,
+                                                               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, ...);
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentWithFlagsf(IMG_CONST
+                                                                  PVRSRV_CONNECTION
+                                                                  *
+                                                                  psConnection,
+                                                                  IMG_UINT32
+                                                                  ui32Flags,
+                                                                  IMG_CONST
+                                                                  IMG_CHAR *
+                                                                  pszFormat,
+                                                                  ...);
+
+        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_CONNECTION *
+                                                       psConnection,
+                                                       IMG_CHAR * pszFileName,
+                                                       IMG_UINT32
+                                                       ui32FileOffset,
+                                                       IMG_UINT32 ui32Width,
+                                                       IMG_UINT32 ui32Height,
+                                                       IMG_UINT32
+                                                       ui32StrideInBytes,
+                                                       IMG_DEV_VIRTADDR
+                                                       sDevBaseAddr,
+                                                       IMG_UINT32 ui32Size,
+                                                       PDUMP_PIXEL_FORMAT
+                                                       ePixelFormat,
+                                                       PDUMP_MEM_FORMAT
+                                                       eMemFormat,
+                                                       IMG_UINT32
+                                                       ui32PDumpFlags);
+
+        IMG_IMPORT
+           PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegRead(IMG_CONST
+                                                        PVRSRV_CONNECTION *
+                                                        psConnection,
+                                                        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_CONNECTION
+                                                                  *
+                                                                  psConnection,
+                                                                  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_UINT32 IMG_CALLCONV PVRSRVGetCurrentProcessID(void);
+
+       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_UINT32
+                                                                ui32Size);
+       IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem(IMG_UINT32
+                                                                 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_UINT32 ui32Size);
+       IMG_IMPORT IMG_VOID PVRSRVMemSet(IMG_VOID * pvDest, IMG_UINT8 ui8Value,
+                                        IMG_UINT32 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);
+
+#if (defined(DEBUG) && defined(__linux__))
+       IMG_PVOID PVRSRVAllocUserModeMemTracking(IMG_UINT32 ui32Size,
+                                                IMG_CHAR * pszFileName,
+                                                IMG_UINT32 ui32LineNumber);
+       IMG_PVOID PVRSRVCallocUserModeMemTracking(IMG_UINT32 ui32Size,
+                                                 IMG_CHAR * pszFileName,
+                                                 IMG_UINT32 ui32LineNumber);
+       IMG_VOID PVRSRVFreeUserModeMemTracking(IMG_VOID * pvMem);
+       IMG_PVOID PVRSRVReallocUserModeMemTracking(IMG_VOID * pvMem,
+                                                  IMG_UINT32 ui32NewSize,
+                                                  IMG_CHAR * pszFileName,
+                                                  IMG_UINT32 ui32LineNumber);
+#endif
+
+       IMG_IMPORT PVRSRV_ERROR PVRSRVEventObjectWait(PVRSRV_CONNECTION *
+                                                     psConnection,
+                                                     IMG_HANDLE hOSEvent);
+
+#define TIME_NOT_PASSED_UINT32(a,b,c)          ((a - b) < c)
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/services_headers.h b/pvr/services_headers.h
new file mode 100644 (file)
index 0000000..3e25dee
--- /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 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"
+
+#endif
diff --git a/pvr/servicesext.h b/pvr/servicesext.h
new file mode 100644 (file)
index 0000000..cd35306
--- /dev/null
@@ -0,0 +1,398 @@
+/**********************************************************************
+ *
+ * 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 = 1,
+       PVRSRV_ERROR_OUT_OF_MEMORY = 2,
+       PVRSRV_ERROR_TOO_FEW_BUFFERS = 3,
+       PVRSRV_ERROR_SYMBOL_NOT_FOUND = 4,
+       PVRSRV_ERROR_OUT_OF_HSPACE = 5,
+       PVRSRV_ERROR_INVALID_PARAMS = 6,
+       PVRSRV_ERROR_TILE_MAP_FAILED = 7,
+       PVRSRV_ERROR_INIT_FAILURE = 8,
+       PVRSRV_ERROR_CANT_REGISTER_CALLBACK = 9,
+       PVRSRV_ERROR_INVALID_DEVICE = 10,
+       PVRSRV_ERROR_NOT_OWNER = 11,
+       PVRSRV_ERROR_BAD_MAPPING = 12,
+       PVRSRV_ERROR_TIMEOUT = 13,
+       PVRSRV_ERROR_NO_PRIMARY = 14,
+       PVRSRV_ERROR_FLIP_CHAIN_EXISTS = 15,
+       PVRSRV_ERROR_CANNOT_ACQUIRE_SYSDATA = 16,
+       PVRSRV_ERROR_SCENE_INVALID = 17,
+       PVRSRV_ERROR_STREAM_ERROR = 18,
+       PVRSRV_ERROR_INVALID_INTERRUPT = 19,
+       PVRSRV_ERROR_FAILED_DEPENDENCIES = 20,
+       PVRSRV_ERROR_CMD_NOT_PROCESSED = 21,
+       PVRSRV_ERROR_CMD_TOO_BIG = 22,
+       PVRSRV_ERROR_DEVICE_REGISTER_FAILED = 23,
+       PVRSRV_ERROR_FIFO_SPACE = 24,
+       PVRSRV_ERROR_TA_RECOVERY = 25,
+       PVRSRV_ERROR_INDOSORLOWPOWER = 26,
+       PVRSRV_ERROR_TOOMANYBUFFERS = 27,
+       PVRSRV_ERROR_NOT_SUPPORTED = 28,
+       PVRSRV_ERROR_PROCESSING_BLOCKED = 29,
+
+       PVRSRV_ERROR_CANNOT_FLUSH_QUEUE = 31,
+       PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE = 32,
+       PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS = 33,
+       PVRSRV_ERROR_RETRY = 34,
+
+       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_POWER_STATE_ {
+       PVRSRV_POWER_Unspecified = -1,
+       PVRSRV_POWER_STATE_D0 = 0,
+       PVRSRV_POWER_STATE_D1 = 1,
+       PVRSRV_POWER_STATE_D2 = 2,
+       PVRSRV_POWER_STATE_D3 = 3,
+       PVRSRV_POWER_STATE_D4 = 4,
+
+       PVRSRV_POWER_STATE_FORCE_I32 = 0x7fffffff
+} PVR_POWER_STATE, *PPVR_POWER_STATE;
+
+typedef PVRSRV_ERROR(*PFN_PRE_POWER) (IMG_HANDLE, PVR_POWER_STATE,
+                                     PVR_POWER_STATE);
+typedef PVRSRV_ERROR(*PFN_POST_POWER) (IMG_HANDLE, PVR_POWER_STATE,
+                                      PVR_POWER_STATE);
+
+typedef PVRSRV_ERROR(*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR(*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL);
+
+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_YUV420 = 5,
+       PVRSRV_PIXEL_FORMAT_YUV444 = 6,
+       PVRSRV_PIXEL_FORMAT_VUY444 = 7,
+       PVRSRV_PIXEL_FORMAT_GREY_SCALE = 8,
+       PVRSRV_PIXEL_FORMAT_YUYV = 9,
+       PVRSRV_PIXEL_FORMAT_YVYU = 10,
+       PVRSRV_PIXEL_FORMAT_UYVY = 11,
+       PVRSRV_PIXEL_FORMAT_VYUY = 12,
+       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_DXT1 = 24,
+       PVRSRV_PIXEL_FORMAT_IMC2 = 25,
+
+       PVRSRV_PIXEL_FORMAT_XRGB8888,
+       PVRSRV_PIXEL_FORMAT_XBGR8888,
+       PVRSRV_PIXEL_FORMAT_XRGB4444,
+       PVRSRV_PIXEL_FORMAT_G16R16,
+       PVRSRV_PIXEL_FORMAT_G16R16F,
+       PVRSRV_PIXEL_FORMAT_ARGB8332,
+       PVRSRV_PIXEL_FORMAT_A2RGB10,
+       PVRSRV_PIXEL_FORMAT_A2BGR10,
+       PVRSRV_PIXEL_FORMAT_B10GR11,
+       PVRSRV_PIXEL_FORMAT_GR88,
+       PVRSRV_PIXEL_FORMAT_ABGR16,
+       PVRSRV_PIXEL_FORMAT_ABGR32,
+       PVRSRV_PIXEL_FORMAT_BGR32,
+       PVRSRV_PIXEL_FORMAT_GR32,
+       PVRSRV_PIXEL_FORMAT_ABGR16F,
+       PVRSRV_PIXEL_FORMAT_ABGR32F,
+       PVRSRV_PIXEL_FORMAT_R32,
+       PVRSRV_PIXEL_FORMAT_R32F,
+       PVRSRV_PIXEL_FORMAT_R8,
+       PVRSRV_PIXEL_FORMAT_A8,
+       PVRSRV_PIXEL_FORMAT_P8,
+       PVRSRV_PIXEL_FORMAT_L8,
+       PVRSRV_PIXEL_FORMAT_A8L8,
+       PVRSRV_PIXEL_FORMAT_A4L4,
+       PVRSRV_PIXEL_FORMAT_R1,
+       PVRSRV_PIXEL_FORMAT_L16,
+       PVRSRV_PIXEL_FORMAT_R16,
+       PVRSRV_PIXEL_FORMAT_R16F,
+       PVRSRV_PIXEL_FORMAT_L6V5U5,
+       PVRSRV_PIXEL_FORMAT_V8U8,
+       PVRSRV_PIXEL_FORMAT_V16U16,
+       PVRSRV_PIXEL_FORMAT_QWVU8888,
+       PVRSRV_PIXEL_FORMAT_XLVU8888,
+       PVRSRV_PIXEL_FORMAT_QWVU16,
+       PVRSRV_PIXEL_FORMAT_D16,
+       PVRSRV_PIXEL_FORMAT_D24S8,
+       PVRSRV_PIXEL_FORMAT_D24X8,
+       PVRSRV_PIXEL_FORMAT_D32F,
+       PVRSRV_PIXEL_FORMAT_R8G8_B8G8,
+       PVRSRV_PIXEL_FORMAT_G8R8_G8B8,
+       PVRSRV_PIXEL_FORMAT_YUY2,
+       PVRSRV_PIXEL_FORMAT_DXT23,
+       PVRSRV_PIXEL_FORMAT_DXT45,
+       PVRSRV_PIXEL_FORMAT_G32R32F,
+       PVRSRV_PIXEL_FORMAT_NV11,
+       PVRSRV_PIXEL_FORMAT_NV12,
+
+       PVRSRV_PIXEL_FORMAT_X24G8R32,
+       PVRSRV_PIXEL_FORMAT_G8R24,
+       PVRSRV_PIXEL_FORMAT_E5BGR9,
+
+       PVRSRV_PIXEL_FORMAT_BC1,
+       PVRSRV_PIXEL_FORMAT_BC2,
+       PVRSRV_PIXEL_FORMAT_BC3,
+       PVRSRV_PIXEL_FORMAT_BC4,
+       PVRSRV_PIXEL_FORMAT_BC5,
+
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY,
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV,
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU,
+       PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY,
+
+       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;
+
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED         (1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY          (1<<1)
+
+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_UINT32 *,
+                                           IMG_VOID **,
+                                           IMG_HANDLE *, IMG_BOOL *);
+
+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_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;
+
+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)
+
+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;
+} BUFFER_INFO;
+
+typedef enum _OVERLAY_DEINTERLACE_MODE_ {
+       WEAVE = 0x0,
+       BOB_ODD,
+       BOB_EVEN,
+       BOB_EVEN_NONINTERLEAVED
+} OVERLAY_DEINTERLACE_MODE;
+
+#endif
diff --git a/pvr/servicesint.h b/pvr/servicesint.h
new file mode 100644 (file)
index 0000000..8ccdd45
--- /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 
+ *
+ ******************************************************************************/
+
+#if !defined (__SERVICESINT_H__)
+#define __SERVICESINT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "services.h"
+#include "sysinfo.h"
+
+#define HWREC_DEFAULT_TIMEOUT  (500)
+
+#define DRIVERNAME_MAXLENGTH   (100)
+
+       typedef struct _PVRSRV_KERNEL_MEM_INFO_ {
+
+               IMG_PVOID pvLinAddrKM;
+
+               IMG_DEV_VIRTADDR sDevVAddr;
+
+               IMG_UINT32 ui32Flags;
+
+               IMG_UINT32 ui32AllocSize;
+
+               PVRSRV_MEMBLK sMemBlk;
+
+               IMG_PVOID pvSysBackupBuffer;
+
+               struct _PVRSRV_KERNEL_SYNC_INFO_ *psKernelSyncInfo;
+
+       } 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;
+
+       } PVRSRV_KERNEL_SYNC_INFO;
+
+       typedef struct _PVRSRV_DEVICE_SYNC_OBJECT_ {
+               IMG_UINT32 ui32ReadOpPendingVal;
+               IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+               IMG_UINT32 ui32WriteOpPendingVal;
+               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_UINT32 ui32CmdSize;
+               IMG_UINT32 ui32DevIndex;
+               IMG_UINT32 CommandType;
+               IMG_UINT32 ui32DstSyncCount;
+               IMG_UINT32 ui32SrcSyncCount;
+               PVRSRV_SYNC_OBJECT *psDstSync;
+               PVRSRV_SYNC_OBJECT *psSrcSync;
+               IMG_UINT32 ui32DataSize;
+               IMG_UINT32 ui32ProcessID;
+               IMG_VOID *pvData;
+       } PVRSRV_COMMAND, *PPVRSRV_COMMAND;
+
+       typedef struct _PVRSRV_QUEUE_INFO_ {
+               IMG_VOID *pvLinQueueKM;
+               IMG_VOID *pvLinQueueUM;
+               volatile IMG_UINT32 ui32ReadOffset;
+               volatile IMG_UINT32 ui32WriteOffset;
+               IMG_UINT32 *pui32KickerAddrKM;
+               IMG_UINT32 *pui32KickerAddrUM;
+               IMG_UINT32 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_UINT32 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 (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/sgx530defs.h b/pvr/sgx530defs.h
new file mode 100644 (file)
index 0000000..1a4b7a0
--- /dev/null
@@ -0,0 +1,427 @@
+/**********************************************************************
+ *
+ * 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 _SGX530DEFS_KM_H_
+#define _SGX530DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK      0x00000003
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT     0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000030
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000300
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x00003000
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00030000
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK     0x00300000
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT    20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000
+#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  0x00000010
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000100
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00001000
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00010000
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK  0x00100000
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR                0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK   0x00000003
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT  0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000030
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000300
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x00003000
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00030000
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK  0x00300000
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+#define EUR_CR_CORE_ID                      0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFF
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_REVISION                0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FF
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000
+#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 0xFFFFFFFF
+#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 0xFFFFFFFF
+#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    0x00000001
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK   0x00000002
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT  1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00000008
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00000010
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000040
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   6
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001
+#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_DPM_3D_FREE_LOAD_MASK 0x00000002
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS                 0x012C
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001
+#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 0x80000000
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004
+#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 0x00000002
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001
+#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 0x80000000
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004
+#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 0x00000002
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS                          0x0ABC
+#define EUR_CR_PDS_DOUT_TIMEOUT_DISABLE_MASK 0x00000040
+#define EUR_CR_PDS_DOUT_TIMEOUT_DISABLE_SHIFT 6
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0x0FF00000
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0x0FFFFFF0
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFF
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_PDS_INV2                     0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK            0x00000001
+#define EUR_CR_PDS_INV2_DSC_SHIFT           0
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x3FFFFFFF
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000
+#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      0x00003FFF
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0x0FFFF000
+#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 0xFFFFF000
+#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  0x0FF00000
+#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    0x0FF00000
+#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  0x000000FF
+#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    0x0FF00000
+#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   0x0FF00000
+#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 0x00FFFFFF
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000
+#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 0x00000001
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000E
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000
+#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 0x00000FFF
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000
+#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      0x00FFFFFF
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x03000000
+#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/pvr/sgx_bridge.h b/pvr/sgx_bridge.h
new file mode 100644 (file)
index 0000000..521d2d4
--- /dev/null
@@ -0,0 +1,366 @@
+/**********************************************************************
+ *
+ * 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_SCHEDULECOMMAND              PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+6)
+
+#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_READ_DIFF_COUNTERS           PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+       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 {
+               PVR3DIF4_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 {
+               PVR3DIF4_CLIENT_INFO sClientInfo;
+               PVRSRV_ERROR eError;
+       } PVRSRV_BRIDGE_OUT_GETCLIENTINFO;
+
+       typedef struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO_TAG {
+               IMG_UINT32 ui32BridgeFlags;
+               IMG_HANDLE hDevCookie;
+               PVR3DIF4_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;
+               PVR3DIF4_CCB_KICK sCCBKick;
+       } PVRSRV_BRIDGE_IN_DOKICK;
+
+#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_SCHEDULECOMMAND_TAG {
+               IMG_UINT32 ui32BridgeFlags;
+               IMG_HANDLE hDevCookie;
+               PVRSRV_SGX_COMMAND_TYPE eCommandType;
+               PVRSRV_SGX_COMMAND *psCommandData;
+
+       } PVRSRV_BRIDGE_IN_SCHEDULECOMMAND;
+
+       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
+                   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_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;
+               PVR3DIF4_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_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_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_UINT32 ui32DumpFrameNum;
+               IMG_UINT32 ui32TAKickCount;
+               IMG_BOOL bLastFrame;
+               IMG_UINT32 *pui32Registers;
+               IMG_UINT32 ui32NumRegisters;
+       } PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS;
+
+#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_DIFF_COUNTERS_TAG {
+               IMG_UINT32 ui32BridgeFlags;
+               IMG_HANDLE hDevCookie;
+               IMG_UINT32 ui32Reg;
+               IMG_BOOL bNew;
+               IMG_UINT32 ui32New;
+               IMG_UINT32 ui32NewReset;
+               IMG_UINT32 ui32CountersReg;
+       } PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS;
+
+       typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS_TAG {
+               PVRSRV_ERROR eError;
+               IMG_UINT32 ui32Old;
+               IMG_UINT32 ui32Time;
+               IMG_BOOL bActive;
+               PVRSRV_SGXDEV_DIFF_INFO sDiffs;
+       } PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS;
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/sgx_bridge_km.h b/pvr/sgx_bridge_km.h
new file mode 100644 (file)
index 0000000..86c5525
--- /dev/null
@@ -0,0 +1,152 @@
+/**********************************************************************
+ *
+ * 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);
+
+#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,
+                                    PVR3DIF4_CCB_KICK * psCCBKick);
+
+       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,
+                                           PVR3DIF4_CLIENT_INFO *
+                                           psClientInfo);
+
+       IMG_IMPORT
+           PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO * psDevInfo,
+                                         SGX_MISC_INFO * psMiscInfo);
+
+#if defined(SUPPORT_SGX_HWPERF)
+       IMG_IMPORT
+           PVRSRV_ERROR SGXReadDiffCountersKM(IMG_HANDLE hDevHandle,
+                                              IMG_UINT32 ui32Reg,
+                                              IMG_UINT32 * pui32Old,
+                                              IMG_BOOL bNew,
+                                              IMG_UINT32 ui32New,
+                                              IMG_UINT32 ui32NewReset,
+                                              IMG_UINT32 ui32CountersReg,
+                                              IMG_UINT32 * pui32Time,
+                                              IMG_BOOL * pbActive,
+                                              PVRSRV_SGXDEV_DIFF_INFO *
+                                              psDiffs);
+#endif
+
+       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 ***
+                                 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,
+                                IMG_UINT32 ui32TotalPBSize,
+                                IMG_HANDLE * phSharedPBDesc,
+                                PVRSRV_KERNEL_MEM_INFO **
+                                psSharedPBDescSubKernelMemInfos,
+                                IMG_UINT32
+                                ui32SharedPBDescSubKernelMemInfosCount);
+
+       IMG_IMPORT PVRSRV_ERROR
+           SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+                                   PVR3DIF4_INTERNAL_DEVINFO *
+                                   psSGXInternalDevInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/sgxapi_km.h b/pvr/sgxapi_km.h
new file mode 100644 (file)
index 0000000..ea7ba9b
--- /dev/null
@@ -0,0 +1,206 @@
+/**********************************************************************
+ *
+ * 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_GENERAL_HEAP_ID                                    0
+#define SGX_TADATA_HEAP_ID                                     1
+#define SGX_KERNEL_CODE_HEAP_ID                                2
+#define SGX_VIDEO_CODE_HEAP_ID                         3
+#define SGX_KERNEL_VIDEO_DATA_HEAP_ID          4
+#define SGX_PIXELSHADER_HEAP_ID                                5
+#define SGX_VERTEXSHADER_HEAP_ID                       6
+#define SGX_PDSPIXEL_CODEDATA_HEAP_ID          7
+#define SGX_PDSVERTEX_CODEDATA_HEAP_ID         8
+#define SGX_SYNCINFO_HEAP_ID                           9
+#define SGX_3DPARAMETERS_HEAP_ID                       10
+#define SGX_GENERAL_MAPPING_HEAP_ID                    11
+#define SGX_UNDEFINED_HEAP_ID                          (~0LU)
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_2D_HEAP_ID                                 12
+#define SGX_MAX_HEAP_ID                                        13
+#else
+#define SGX_MAX_HEAP_ID                                        12
+#endif
+
+#define SGX_MAX_TA_STATUS_VALS 32
+#define SGX_MAX_3D_STATUS_VALS 2
+
+#define SGX_MAX_SRC_SYNCS                      4
+
+       typedef struct _SGX_SLAVE_PORT_ {
+               IMG_PVOID pvData;
+               IMG_UINT32 ui32DataRange;
+               IMG_PUINT32 pui32Offset;
+               IMG_SYS_PHYADDR sPhysBase;
+       } SGX_SLAVE_PORT;
+
+#ifdef SUPPORT_SGX_HWPERF
+
+#define PVRSRV_SGX_HWPERF_CBSIZE                                       0x100
+
+#define PVRSRV_SGX_HWPERF_INVALID                                      1
+#define PVRSRV_SGX_HWPERF_TRANSFER                                     2
+#define PVRSRV_SGX_HWPERF_TA                                           3
+#define PVRSRV_SGX_HWPERF_3D                                           4
+
+#define PVRSRV_SGX_HWPERF_ON                                           0x40
+
+       typedef struct _PVRSRV_SGX_HWPERF_CBDATA_ {
+               IMG_UINT32 ui32FrameNo;
+               IMG_UINT32 ui32Type;
+               IMG_UINT32 ui32StartTimeWraps;
+               IMG_UINT32 ui32StartTime;
+               IMG_UINT32 ui32EndTimeWraps;
+               IMG_UINT32 ui32EndTime;
+               IMG_UINT32 ui32ClockSpeed;
+               IMG_UINT32 ui32TimeMax;
+       } PVRSRV_SGX_HWPERF_CBDATA;
+
+       typedef struct _PVRSRV_SGX_HWPERF_CB_ {
+               IMG_UINT32 ui32Woff;
+               IMG_UINT32 ui32Roff;
+               PVRSRV_SGX_HWPERF_CBDATA
+                   psHWPerfCBData[PVRSRV_SGX_HWPERF_CBSIZE];
+       } PVRSRV_SGX_HWPERF_CB;
+
+       typedef struct _SGX_MISC_INFO_HWPERF_RETRIEVE_CB {
+               PVRSRV_SGX_HWPERF_CBDATA *psHWPerfData;
+               IMG_UINT32 ui32ArraySize;
+               IMG_UINT32 ui32DataCount;
+               IMG_UINT32 ui32Time;
+       } SGX_MISC_INFO_HWPERF_RETRIEVE_CB;
+#endif
+
+       typedef enum _SGX_MISC_INFO_REQUEST_ {
+               SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
+#ifdef SUPPORT_SGX_HWPERF
+               SGX_MISC_INFO_REQUEST_HWPERF_CB_ON,
+               SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF,
+               SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB,
+#endif
+               SGX_MISC_INFO_REQUEST_FORCE_I16 = 0x7fff
+       } SGX_MISC_INFO_REQUEST;
+
+       typedef struct _SGX_MISC_INFO_ {
+               SGX_MISC_INFO_REQUEST eRequest;
+
+               union {
+                       IMG_UINT32 reserved;
+                       IMG_UINT32 ui32SGXClockSpeed;
+#ifdef SUPPORT_SGX_HWPERF
+                       SGX_MISC_INFO_HWPERF_RETRIEVE_CB sRetrieveCB;
+#endif
+               } uData;
+       } SGX_MISC_INFO;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_MAX_BLT_SRC_SYNCS               3
+#endif
+
+#define PVR3DIF4_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH             256
+
+       typedef struct _PVR3DIF4_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[PVR3DIF4_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH];
+       } PVR3DIF4_KICKTA_DUMPBITMAP, *PPVR3DIF4_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 _PVR3DIF4_KICKTA_DUMP_ROFF_ {
+               IMG_HANDLE hKernelMemInfo;
+               IMG_UINT32 uiAllocIndex;
+               IMG_UINT32 ui32Offset;
+               IMG_UINT32 ui32Value;
+               IMG_PCHAR pszName;
+       } PVR3DIF4_KICKTA_DUMP_ROFF, *PPVR3DIF4_KICKTA_DUMP_ROFF;
+
+       typedef struct _PVR3DIF4_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_PCHAR pszName;
+       } PVR3DIF4_KICKTA_DUMP_BUFFER, *PPVR3DIF4_KICKTA_DUMP_BUFFER;
+
+#ifdef PDUMP
+       typedef struct _PVR3DIF4_KICKTA_PDUMP_ {
+
+               PPVR3DIF4_KICKTA_DUMPBITMAP psPDumpBitmapArray;
+               IMG_UINT32 ui32PDumpBitmapSize;
+
+               PPVR3DIF4_KICKTA_DUMP_BUFFER psBufferArray;
+               IMG_UINT32 ui32BufferArraySize;
+
+               PPVR3DIF4_KICKTA_DUMP_ROFF psROffArray;
+               IMG_UINT32 ui32ROffArraySize;
+       } PVR3DIF4_KICKTA_PDUMP, *PPVR3DIF4_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/pvr/sgxconfig.h b/pvr/sgxconfig.h
new file mode 100644 (file)
index 0000000..5f0d4d2
--- /dev/null
@@ -0,0 +1,127 @@
+/**********************************************************************
+ *
+ * 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__
+
+#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
+#define SGX_ADDRESS_SPACE_SIZE                         32
+
+#define SGX_GENERAL_HEAP_BASE                          0x00400000
+#define SGX_GENERAL_HEAP_SIZE                          (0x78000000-0x00800000)
+
+#define SGX_TADATA_HEAP_BASE                           0x78000000
+#define SGX_TADATA_HEAP_SIZE                           (0x08000000-0x00400000)
+
+#define SGX_KERNEL_CODE_HEAP_BASE                      0x80000000
+#define SGX_KERNEL_CODE_HEAP_SIZE                      0x00080000
+
+#define SGX_VIDEO_CODE_HEAP_BASE                       0x81000000
+#define SGX_VIDEO_CODE_HEAP_SIZE                       0x00080000
+
+#define SGX_KERNEL_VIDEO_DATA_HEAP_BASE                0x82000000
+#define SGX_KERNEL_VIDEO_DATA_HEAP_SIZE                0x05000000
+
+#define SGX_PIXELSHADER_HEAP_BASE                      0x88000000
+#define SGX_PIXELSHADER_HEAP_SIZE                      0x00500000
+
+#define SGX_VERTEXSHADER_HEAP_BASE                     0x89000000
+#define SGX_VERTEXSHADER_HEAP_SIZE                     0x00200000
+
+#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE                0x8A000000
+#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE                0x02000000
+
+#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE       0x8C000000
+#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE       0x02000000
+
+#define SGX_SYNCINFO_HEAP_BASE                         0xA0000000
+#define SGX_SYNCINFO_HEAP_SIZE                         0x01000000
+
+#define SGX_3DPARAMETERS_HEAP_BASE                     0xC0000000
+#define SGX_3DPARAMETERS_HEAP_SIZE                     (0x10000000-0x00400000)
+
+#define SGX_2D_HEAP_BASE                                       0xD0000000
+#define SGX_2D_HEAP_SIZE                                       (0x08000000-0x00400000)
+
+#define SGX_GENERAL_MAPPING_HEAP_BASE          0xD8000000
+#define SGX_GENERAL_MAPPING_HEAP_SIZE          (0x08000000-0x00400000)
+
+#define SGX_CORE_IDENTIFIED
+#endif
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+#define SGX_ADDRESS_SPACE_SIZE                         28
+
+#define SGX_GENERAL_HEAP_BASE                          0x00400000
+#define SGX_GENERAL_HEAP_SIZE                          (0x07000000-0x00401000)
+
+#define SGX_TADATA_HEAP_BASE                           0x07000000
+#define SGX_TADATA_HEAP_SIZE                           (0x01000000-0x00001000)
+
+#define SGX_3DPARAMETERS_HEAP_BASE                     0x08000000
+#define SGX_3DPARAMETERS_HEAP_SIZE                     (0x04000000-0x00001000)
+
+#define SGX_GENERAL_MAPPING_HEAP_BASE          0x0C000000
+#define SGX_GENERAL_MAPPING_HEAP_SIZE          (0x01000000-0x00001000)
+
+#define SGX_PIXELSHADER_HEAP_BASE                      0x0D000000
+#define SGX_PIXELSHADER_HEAP_SIZE                      0x00500000
+
+#define SGX_VERTEXSHADER_HEAP_BASE                     0x0D800000
+#define SGX_VERTEXSHADER_HEAP_SIZE                     0x00200000
+
+#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE                0x0E000000
+#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE                (0x00800000-0x00001000)
+
+#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE       0x0E800000
+#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE       (0x00800000-0x00001000)
+
+#define SGX_KERNEL_CODE_HEAP_BASE                      0x0F000000
+#define SGX_KERNEL_CODE_HEAP_SIZE                      0x00080000
+
+#define SGX_VIDEO_CODE_HEAP_BASE                       0x0F400000
+#define SGX_VIDEO_CODE_HEAP_SIZE                       0x00080000
+
+#define SGX_KERNEL_VIDEO_DATA_HEAP_BASE                0x0F800000
+#define SGX_KERNEL_VIDEO_DATA_HEAP_SIZE                (0x00400000-0x00001000)
+
+#define SGX_SYNCINFO_HEAP_BASE                         0x0FC00000
+#define SGX_SYNCINFO_HEAP_SIZE                         (0x00400000-0x00001000)
+
+#define SGX_CORE_IDENTIFIED
+#endif
+
+#if !defined(SGX_CORE_IDENTIFIED)
+#error "sgxconfig.h: ERROR: unspecified SGX Core version"
+#endif
+
+#endif
diff --git a/pvr/sgxcoretypes.h b/pvr/sgxcoretypes.h
new file mode 100644 (file)
index 0000000..ff5f6b8
--- /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 
+ *
+ ******************************************************************************/
+
+#ifndef _SGXCORETYPES_KM_H_
+#define _SGXCORETYPES_KM_H_
+
+typedef enum {
+       SGX_CORE_ID_INVALID = 0,
+       SGX_CORE_ID_530 = 2,
+       SGX_CORE_ID_535 = 3,
+} SGX_CORE_ID_TYPE;
+
+typedef struct _SGX_CORE_INFO {
+       SGX_CORE_ID_TYPE eID;
+       IMG_UINT32 uiRev;
+} SGX_CORE_INFO, *PSGX_CORE_INFO;
+
+#endif
diff --git a/pvr/sgxdefs.h b/pvr/sgxdefs.h
new file mode 100644 (file)
index 0000000..f58ca26
--- /dev/null
@@ -0,0 +1,57 @@
+/**********************************************************************
+ *
+ * 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_
+
+#if defined(SGX530)
+#include "sgx530defs.h"
+#else
+#if defined(SGX535)
+#include "sgx535defs.h"
+#else
+#if defined(SGX520)
+#include "sgx520defs.h"
+#else
+#if defined(SGX535_V1_1)
+#include "sgx535defs.h"
+#else
+#if defined(SGX540)
+#include "sgx540defs.h"
+#else
+#if defined(SGX531)
+#include "sgx531defs.h"
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#include "sgxerrata.h"
+#include "sgxfeaturedefs.h"
+
+#endif
diff --git a/pvr/sgxerrata.h b/pvr/sgxerrata.h
new file mode 100644 (file)
index 0000000..7a02d93
--- /dev/null
@@ -0,0 +1,191 @@
+/**********************************************************************
+ *
+ * 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
+#else
+#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+#else
+#error "sgxerrata.h: SGX520 Core Revision unspecified"
+#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 == 103
+#else
+#if SGX_CORE_REV == 110
+#else
+#if SGX_CORE_REV == 111
+#else
+#if SGX_CORE_REV == 120
+#else
+#if SGX_CORE_REV == 121
+#else
+#if SGX_CORE_REV == 125
+#else
+#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+#else
+#error "sgxerrata.h: SGX530 Core Revision unspecified"
+#endif
+#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 == 100
+#else
+#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+#else
+#error "sgxerrata.h: SGX531 Core Revision unspecified"
+#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 == 111
+#define FIX_HW_BRN_23281
+#define FIX_HW_BRN_23410
+#define FIX_HW_BRN_22693
+#define FIX_HW_BRN_22997
+#define FIX_HW_BRN_23030
+#else
+#if SGX_CORE_REV == 1111
+#define FIX_HW_BRN_23281
+#define FIX_HW_BRN_23410
+#define FIX_HW_BRN_22693
+#define FIX_HW_BRN_22997
+#define FIX_HW_BRN_23030
+#else
+#if SGX_CORE_REV == 112
+#define FIX_HW_BRN_23281
+#define FIX_HW_BRN_23410
+#define FIX_HW_BRN_22693
+#define FIX_HW_BRN_22997
+#define FIX_HW_BRN_23030
+#else
+#if SGX_CORE_REV == 113
+#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_23944
+#define FIX_HW_BRN_23410
+#else
+#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+#else
+#error "sgxerrata.h: SGX535 Core Revision unspecified"
+
+#endif
+#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_25503
+#else
+#if SGX_CORE_REV == 110
+#define FIX_HW_BRN_25503
+#else
+#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+#else
+#error "sgxerrata.h: SGX540 Core Revision unspecified"
+#endif
+#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/pvr/sgxfeaturedefs.h b/pvr/sgxfeaturedefs.h
new file mode 100644 (file)
index 0000000..78e0061
--- /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 
+ *
+ ******************************************************************************/
+
+#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(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_2D_HARDWARE
+#define SGX_FEATURE_AUTOCLOCKGATING
+#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
+#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
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if !defined(SGX_DONT_SWITCH_OFF_FEATURES)
+
+#if defined(FIX_HW_BRN_22693)
+#undef SGX_FEATURE_AUTOCLOCKGATING
+#endif
+
+#endif
+
+#include "img_types.h"
+
+#include "sgxcoretypes.h"
diff --git a/pvr/sgxinfo.h b/pvr/sgxinfo.h
new file mode 100644 (file)
index 0000000..8f0c407
--- /dev/null
@@ -0,0 +1,367 @@
+/**********************************************************************
+ *
+ * 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"
+
+#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 struct _SGX_BRIDGE_INIT_INFO_ {
+       IMG_HANDLE hKernelCCBMemInfo;
+       IMG_HANDLE hKernelCCBCtlMemInfo;
+       IMG_HANDLE hKernelCCBEventKickerMemInfo;
+       IMG_HANDLE hKernelSGXHostCtlMemInfo;
+       IMG_UINT32 ui32TAKickAddress;
+       IMG_UINT32 ui32VideoHandlerAddress;
+#if defined(SGX_SUPPORT_HWPROFILING)
+       IMG_HANDLE hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+       IMG_HANDLE hKernelHWPerfCBMemInfo;
+#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 ui32ClkGateCtl;
+       IMG_UINT32 ui32ClkGateCtl2;
+       IMG_UINT32 ui32ClkGateStatusMask;
+
+       IMG_UINT32 ui32CacheControl;
+
+       IMG_UINT32 asInitDevData[SGX_MAX_DEV_DATA];
+       IMG_HANDLE asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+       SGX_INIT_SCRIPTS sScripts;
+
+} SGX_BRIDGE_INIT_INFO;
+
+typedef struct _PVRSRV_SGX_COMMAND_ {
+       IMG_UINT32 ui32ServiceAddress;
+       IMG_UINT32 ui32Data[7];
+} PVRSRV_SGX_COMMAND;
+
+typedef struct _PVRSRV_SGX_KERNEL_CCB_ {
+       PVRSRV_SGX_COMMAND asCommands[256];
+} PVRSRV_SGX_KERNEL_CCB;
+
+typedef struct _PVRSRV_SGX_CCB_CTL_ {
+       IMG_UINT32 ui32WriteOffset;
+       IMG_UINT32 ui32ReadOffset;
+} PVRSRV_SGX_CCB_CTL;
+
+#define SGX_AUXCCBFLAGS_SHARED                                 0x00000001
+
+typedef enum _PVRSRV_SGX_COMMAND_TYPE_ {
+       PVRSRV_SGX_COMMAND_EDM_KICK = 0,
+       PVRSRV_SGX_COMMAND_VIDEO_KICK = 1,
+
+       PVRSRV_SGX_COMMAND_FORCE_I32 = 0xFFFFFFFF,
+
+} PVRSRV_SGX_COMMAND_TYPE;
+
+#define PVRSRV_CCBFLAGS_RASTERCMD                      0x1
+#define PVRSRV_CCBFLAGS_TRANSFERCMD                    0x2
+#define PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD      0x3
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_CCBFLAGS_2DCMD                          0x4
+#endif
+
+#define        SGX_BIF_INVALIDATE_PTCACHE      0x1
+#define        SGX_BIF_INVALIDATE_PDCACHE      0x2
+
+typedef struct _PVR3DIF4_CCB_KICK_ {
+       PVRSRV_SGX_COMMAND_TYPE eCommand;
+       PVRSRV_SGX_COMMAND sCommand;
+       IMG_HANDLE hCCBKernelMemInfo;
+       IMG_HANDLE hRenderSurfSyncInfo;
+
+       IMG_UINT32 ui32NumTAStatusVals;
+       IMG_HANDLE ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+
+       IMG_UINT32 ui32Num3DStatusVals;
+       IMG_HANDLE ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+
+       IMG_BOOL bFirstKickOrResume;
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+       IMG_BOOL bTerminateOrAbort;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+       IMG_BOOL bKickRender;
+#endif
+
+       IMG_UINT32 ui32CCBOffset;
+
+       IMG_UINT32 ui32NumSrcSyncs;
+       IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+
+       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
+} PVR3DIF4_CCB_KICK;
+
+#define SGX_VIDEO_USE_CODE_BASE_INDEX          14
+#define SGX_KERNEL_USE_CODE_BASE_INDEX         15
+
+typedef struct _PVRSRV_SGX_HOST_CTL_ {
+
+       volatile IMG_UINT32 ui32PowManFlags;
+#if defined(SUPPORT_HW_RECOVERY)
+       IMG_UINT32 ui32uKernelDetectedLockups;
+       IMG_UINT32 ui32HostDetectedLockups;
+       IMG_UINT32 ui32HWRecoverySampleRate;
+#endif
+       IMG_UINT32 ui32ActivePowManSampleRate;
+       IMG_UINT32 ui32InterruptFlags;
+       IMG_UINT32 ui32InterruptClearFlags;
+
+       IMG_UINT32 ui32ResManFlags;
+       IMG_DEV_VIRTADDR sResManCleanupData;
+
+       IMG_DEV_VIRTADDR sTAHWPBDesc;
+       IMG_DEV_VIRTADDR s3DHWPBDesc;
+       IMG_DEV_VIRTADDR sHostHWPBDesc;
+
+       IMG_UINT32 ui32NumActivePowerEvents;
+
+#if defined(SUPPORT_SGX_HWPERF)
+       IMG_UINT32 ui32HWPerfFlags;
+#endif
+
+       IMG_UINT32 ui32TimeWraps;
+} PVRSRV_SGX_HOST_CTL;
+
+typedef struct _PVR3DIF4_CLIENT_INFO_ {
+       IMG_UINT32 ui32ProcessID;
+       IMG_VOID *pvProcess;
+       PVRSRV_MISC_INFO sMiscInfo;
+
+       IMG_UINT32 asDevData[SGX_MAX_DEV_DATA];
+
+} PVR3DIF4_CLIENT_INFO;
+
+typedef struct _PVR3DIF4_INTERNAL_DEVINFO_ {
+       IMG_UINT32 ui32Flags;
+       IMG_HANDLE hCtlKernelMemInfoHandle;
+       IMG_BOOL bForcePTOff;
+} PVR3DIF4_INTERNAL_DEVINFO;
+
+typedef struct _PVRSRV_SGX_SHARED_CCB_ {
+       PVRSRV_CLIENT_MEM_INFO *psCCBClientMemInfo;
+       PVRSRV_CLIENT_MEM_INFO *psCCBCtlClientMemInfo;
+       IMG_UINT32 *pui32CCBLinAddr;
+       IMG_DEV_VIRTADDR sCCBDevAddr;
+       IMG_UINT32 *pui32WriteOffset;
+       volatile IMG_UINT32 *pui32ReadOffset;
+       IMG_UINT32 ui32Size;
+       IMG_UINT32 ui32AllocGran;
+
+#ifdef PDUMP
+       IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_SGX_SHARED_CCB;
+
+typedef struct _PVRSRV_SGX_CCB_ {
+       PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo;
+       PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo;
+       IMG_PUINT32 pui32CCBLinAddr;
+       IMG_DEV_VIRTADDR sCCBDevAddr;
+       IMG_UINT32 *pui32WriteOffset;
+       volatile IMG_UINT32 *pui32ReadOffset;
+       IMG_UINT32 ui32Size;
+       IMG_UINT32 ui32AllocGran;
+
+#ifdef PDUMP
+       IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_SGX_CCB;
+
+typedef struct _CTL_STATUS_ {
+       IMG_DEV_VIRTADDR sStatusDevAddr;
+       IMG_UINT32 ui32StatusValue;
+} CTL_STATUS, *PCTL_STATUS;
+
+#if defined(TRANSFER_QUEUE)
+#define SGXTQ_MAX_STATUS                                               SGX_MAX_TRANSFER_STATUS_VALS + 2
+typedef struct _PVR3DIF4_CMDTA_SHARED_ {
+       IMG_UINT32 ui32NumTAStatusVals;
+       IMG_UINT32 ui32Num3DStatusVals;
+
+       IMG_UINT32 ui32WriteOpsPendingVal;
+       IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+       IMG_UINT32 ui32ReadOpsPendingVal;
+       IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+
+       IMG_UINT32 ui32TQSyncWriteOpsPendingVal;
+       IMG_DEV_VIRTADDR sTQSyncWriteOpsCompleteDevVAddr;
+       IMG_UINT32 ui32TQSyncReadOpsPendingVal;
+       IMG_DEV_VIRTADDR sTQSyncReadOpsCompleteDevVAddr;
+
+       IMG_UINT32 ui323DTQSyncWriteOpsPendingVal;
+       IMG_DEV_VIRTADDR s3DTQSyncWriteOpsCompleteDevVAddr;
+       IMG_UINT32 ui323DTQSyncReadOpsPendingVal;
+       IMG_DEV_VIRTADDR s3DTQSyncReadOpsCompleteDevVAddr;
+
+       IMG_UINT32 ui32NumSrcSyncs;
+       PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS];
+
+       CTL_STATUS sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+       CTL_STATUS sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
+
+       PVRSRV_DEVICE_SYNC_OBJECT sTA3DDependancy;
+
+} PVR3DIF4_CMDTA_SHARED;
+
+typedef struct _PVR3DIF4_TRANSFERCMD_SHARED_ {
+
+       IMG_UINT32 ui32SrcReadOpPendingVal;
+       IMG_DEV_VIRTADDR sSrcReadOpsCompleteDevAddr;
+
+       IMG_UINT32 ui32SrcWriteOpPendingVal;
+       IMG_DEV_VIRTADDR sSrcWriteOpsCompleteDevAddr;
+
+       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];
+
+       IMG_UINT32 ui32NumSrcSync;
+       IMG_UINT32 ui32NumDstSync;
+
+       IMG_DEV_VIRTADDR sSrcWriteOpsDevVAddr[SGX_MAX_TRANSFER_SYNC_OPS];
+       IMG_DEV_VIRTADDR sSrcReadOpsDevVAddr[SGX_MAX_TRANSFER_SYNC_OPS];
+
+       IMG_DEV_VIRTADDR sDstWriteOpsDevVAddr[SGX_MAX_TRANSFER_SYNC_OPS];
+       IMG_DEV_VIRTADDR sDstReadOpsDevVAddr[SGX_MAX_TRANSFER_SYNC_OPS];
+} PVR3DIF4_TRANSFERCMD_SHARED, *PPVR3DIF4_TRANSFERCMD_SHARED;
+
+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 ui32StatusFirstSync;
+
+#if defined(PDUMP)
+       IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_TRANSFER_SGX_KICK, *PPVRSRV_TRANSFER_SGX_KICK;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _PVR3DIF4_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;
+} PVR3DIF4_2DCMD_SHARED, *PPVR3DIF4_2DCMD_SHARED;
+
+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;
+
+#if defined(PDUMP)
+       IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_2D_SGX_KICK, *PPVRSRV_2D_SGX_KICK;
+#endif
+#endif
+
+#define PVRSRV_SGX_DIFF_NUM_COUNTERS   9
+
+typedef struct _PVRSRV_SGXDEV_DIFF_INFO_ {
+       IMG_UINT32 aui32Counters[PVRSRV_SGX_DIFF_NUM_COUNTERS];
+       IMG_UINT32 ui32Time[2];
+       IMG_UINT32 ui32Marker[2];
+} PVRSRV_SGXDEV_DIFF_INFO, *PPVRSRV_SGXDEV_DIFF_INFO;
+
+#endif
diff --git a/pvr/sgxinfokm.h b/pvr/sgxinfokm.h
new file mode 100644 (file)
index 0000000..3c413a4
--- /dev/null
@@ -0,0 +1,268 @@
+/**********************************************************************
+ *
+ * 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 "sysconfig.h"
+#include "sgxscript.h"
+#include "sgxinfo.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define                SGX_HOSTPORT_PRESENT                    0x00000001UL
+
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST                (1UL << 0)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE       (1UL << 1)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE      (1UL << 2)
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK                                         (1UL << 3)
+
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR                  (1UL << 0)
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1)
+
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_RT_REQUEST      0x01UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_RC_REQUEST      0x02UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_TC_REQUEST      0x04UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_2DC_REQUEST     0x08UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE        0x10UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPD         0x20UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPT         0x40UL
+
+       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;
+
+               IMG_HANDLE hRegMapping;
+
+               IMG_SYS_PHYADDR sRegsPhysBase;
+
+               IMG_UINT32 ui32RegSize;
+
+               IMG_UINT32 ui32CoreClockSpeed;
+               IMG_UINT32 ui32uKernelTimerClock;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+               SGX_SLAVE_PORT s2DSlavePortKM;
+
+               PVRSRV_RESOURCE s2DSlaveportResource;
+
+               IMG_UINT32 ui322DFifoSize;
+               IMG_UINT32 ui322DFifoOffset;
+
+               IMG_HANDLE h2DCmdCookie;
+
+               IMG_HANDLE h2DQueue;
+               IMG_BOOL b2DHWRecoveryInProgress;
+               IMG_BOOL b2DHWRecoveryEndPending;
+               IMG_UINT32 ui322DCompletedBlits;
+               IMG_BOOL b2DLockupSuspected;
+#endif
+
+               IMG_VOID *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;
+               IMG_UINT32 ui32TAKickAddress;
+               IMG_UINT32 ui32TexLoadKickAddress;
+               IMG_UINT32 ui32VideoHandlerAddress;
+#if defined(SGX_SUPPORT_HWPROFILING)
+               PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
+#endif
+               IMG_UINT32 ui32KickTACounter;
+               IMG_UINT32 ui32KickTARenderCounter;
+#if defined(SUPPORT_SGX_HWPERF)
+               PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo;
+               PVRSRV_SGXDEV_DIFF_INFO sDiffInfo;
+               IMG_UINT32 ui32HWGroupRequested;
+               IMG_UINT32 ui32HWReset;
+#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_VOID *pvMMUContextList;
+
+               IMG_BOOL bForcePTOff;
+
+               IMG_UINT32 ui32EDMTaskReg0;
+               IMG_UINT32 ui32EDMTaskReg1;
+
+               IMG_UINT32 ui32ClkGateCtl;
+               IMG_UINT32 ui32ClkGateCtl2;
+               IMG_UINT32 ui32ClkGateStatusMask;
+               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(SUPPORT_HW_RECOVERY)
+
+               IMG_HANDLE hTimer;
+
+               IMG_UINT32 ui32TimeStamp;
+#endif
+
+               IMG_UINT32 ui32NumResets;
+
+               PVRSRV_KERNEL_MEM_INFO *psKernelSGXHostCtlMemInfo;
+               PVRSRV_SGX_HOST_CTL *psSGXHostCtl;
+
+               IMG_UINT32 ui32Flags;
+
+#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
+
+               IMG_UINT32 asSGXDevData[SGX_MAX_DEV_DATA];
+
+       } PVRSRV_SGXDEV_INFO;
+
+       typedef struct _SGX_TIMING_INFORMATION_ {
+               IMG_UINT32 ui32CoreClockSpeed;
+               IMG_UINT32 ui32HWRecoveryFreq;
+               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;
+
+               IMG_SYS_PHYADDR sSPSysPBase;
+               IMG_CPU_PHYADDR sSPCpuPBase;
+               IMG_CPU_VIRTADDR pvSPCpuVBase;
+               IMG_UINT32 ui32SPSize;
+
+               IMG_SYS_PHYADDR sLocalMemSysPBase;
+               IMG_DEV_PHYADDR sLocalMemDevPBase;
+               IMG_CPU_PHYADDR sLocalMemCpuPBase;
+               IMG_UINT32 ui32LocalMemSize;
+
+               IMG_UINT32 ui32IRQ;
+
+               SGX_TIMING_INFORMATION sTimingInfo;
+       } SGX_DEVICE_MAP;
+
+       typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+       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_STUB_PBDESC *psNext;
+       };
+
+       typedef struct _PVRSRV_SGX_CCB_INFO_ {
+               PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo;
+               PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo;
+               PVRSRV_SGX_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);
+
+#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/pvr/sgxinit.c b/pvr/sgxinit.c
new file mode 100644 (file)
index 0000000..18bbe1f
--- /dev/null
@@ -0,0 +1,1618 @@
+/**********************************************************************
+ *
+ * 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 "sgxinfokm.h"
+#include "sgxconfig.h"
+#include "sysconfig.h"
+#include "pvr_bridge_km.h"
+
+#include "pdump_km.h"
+#include "ra.h"
+#include "mmu.h"
+#include "handle.h"
+#include "perproc.h"
+
+#include "sgxutils.h"
+
+#if defined (SGX_FEATURE_2D_HARDWARE)
+#define        SGX_USING_CMD_PROC_LIST
+#endif
+
+IMG_BOOL SGX_ISRHandler(IMG_VOID * pvData);
+
+IMG_UINT32 gui32EventStatusServicesByISR = 0;
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO * psDevInfo, IMG_UINT32 ui32PDUMPFlags);
+
+static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo,
+                                 IMG_BOOL bHardwareRecovery);
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+
+static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+       SGXScheduleProcessQueues(psDeviceNode);
+}
+
+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;
+}
+
+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 =
+           (PVRSRV_SGX_HOST_CTL *) psDevInfo->psKernelSGXHostCtlMemInfo->
+           pvLinAddrKM;
+
+#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
+#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
+
+       eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                           sizeof(PVRSRV_SGX_CCB_INFO),
+                           (IMG_VOID **) & psKernelCCBInfo, 0);
+       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;
+
+       psDevInfo->ui32TAKickAddress = psInitInfo->ui32TAKickAddress;
+
+       psDevInfo->ui32VideoHandlerAddress =
+           psInitInfo->ui32VideoHandlerAddress;
+
+       psDevInfo->bForcePTOff = IMG_FALSE;
+
+       psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
+
+       psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
+       psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
+       psDevInfo->ui32ClkGateCtl = psInitInfo->ui32ClkGateCtl;
+       psDevInfo->ui32ClkGateCtl2 = psInitInfo->ui32ClkGateCtl2;
+       psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
+
+       OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData,
+                 sizeof(psDevInfo->asSGXDevData));
+
+       return PVRSRV_OK;
+
+failed_allockernelccb:
+       DeinitDevInfo(psDevInfo);
+
+       return eError;
+}
+
+static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+       IMG_UINT32 ui32RegVal =
+           EUR_CR_EVENT_TIMER_ENABLE_MASK | psDevInfo->ui32uKernelTimerClock;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_TIMER, ui32RegVal);
+       PDUMPREGWITHFLAGS(EUR_CR_EVENT_TIMER, ui32RegVal,
+                         PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle,
+                             PVR_POWER_STATE eNewPowerState,
+                             PVR_POWER_STATE eCurrentPowerState)
+{
+       if (eNewPowerState != eCurrentPowerState) {
+               PVRSRV_DEVICE_NODE *psDeviceNode =
+                   (PVRSRV_DEVICE_NODE *) hDevHandle;
+               PVRSRV_SGXDEV_INFO *psDevInfo =
+                   (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+
+               if (eNewPowerState == PVRSRV_POWER_STATE_D3) {
+                       PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
+                           psDevInfo->psSGXHostCtl;
+
+#if defined (SGX_FEATURE_AUTOCLOCKGATING) && (!defined(NO_HARDWARE) || defined(PDUMP))
+                       IMG_UINT32 ui32ClockMask =
+                           psDevInfo->ui32ClkGateStatusMask;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+
+                       if (OSDisableTimer(psDevInfo->hTimer) != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SGXPrePowerState: Failed to disable timer"));
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+#endif
+
+                       psSGXHostCtl->ui32PowManFlags |=
+                           PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST;
+
+                       PDUMPCOMMENT
+                           ("TA/3D CCB Control - Trigger power down event on uKernel...");
+                       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                                offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
+                                sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                                MAKEUNIQUETAG(psDevInfo->
+                                              psKernelSGXHostCtlMemInfo));
+
+#if !defined(NO_HARDWARE)
+                       if (PollForValueKM
+                           ((volatile IMG_UINT32 *)(&psSGXHostCtl->
+                                                    ui32PowManFlags),
+                            PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
+                            PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
+                            MAX_HW_TIME_US / WAIT_TRY_COUNT,
+                            WAIT_TRY_COUNT) != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SGXPrePowerState: Wait for chip power off failed."));
+                       }
+#endif
+
+#ifdef PDUMP
+
+                       PDUMPCOMMENT
+                           ("TA/3D CCB Control - Wait for power down event on uKernel...");
+                       PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+                                   offsetof(PVRSRV_SGX_HOST_CTL,
+                                            ui32PowManFlags),
+                                   PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
+                                   PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
+                                   PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE,
+                                   IMG_FALSE,
+                                   MAKEUNIQUETAG(psDevInfo->
+                                                 psKernelSGXHostCtlMemInfo));
+#endif
+
+                       SGXDeinitialise(psDevInfo);
+
+#if defined(SGX_FEATURE_AUTOCLOCKGATING)
+
+#if !defined(NO_HARDWARE)
+                       if (PollForValueKM
+                           ((volatile IMG_UINT32 *)((IMG_UINT8 *) psDevInfo->
+                                                    pvRegsBaseKM +
+                                                    EUR_CR_CLKGATESTATUS), 0,
+                            ui32ClockMask, MAX_HW_TIME_US / WAIT_TRY_COUNT,
+                            WAIT_TRY_COUNT) != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SGXPrePowerState: Wait for chip idle failed."));
+                       }
+#endif
+                       PDUMPREGPOL(EUR_CR_CLKGATESTATUS, 0, ui32ClockMask);
+#endif
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle,
+                              PVR_POWER_STATE eNewPowerState,
+                              PVR_POWER_STATE eCurrentPowerState)
+{
+       if (eNewPowerState != eCurrentPowerState) {
+               PVRSRV_ERROR eError;
+               PVRSRV_DEVICE_NODE *psDeviceNode =
+                   (PVRSRV_DEVICE_NODE *) hDevHandle;
+               PVRSRV_SGXDEV_INFO *psDevInfo =
+                   (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+               SYS_DATA *psSysData;
+
+               eError = SysAcquireData(&psSysData);
+               if (eError != PVRSRV_OK) {
+                       return eError;
+               }
+
+               if (eCurrentPowerState == PVRSRV_POWER_STATE_D3) {
+                       PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
+                           psDevInfo->psSGXHostCtl;
+
+                       psSGXHostCtl->ui32PowManFlags = 0;
+
+                       PDUMPCOMMENT
+                           ("TA/3D CCB Control - Reset Power Manager flags");
+                       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                                offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
+                                sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                                MAKEUNIQUETAG(psDevInfo->
+                                              psKernelSGXHostCtlMemInfo));
+
+                       eError = SGXInitialise(psDevInfo, IMG_FALSE);
+
+                       if (eError != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SGXPostPowerState: SGXInitialise failed"));
+                               return eError;
+                       }
+#if defined(SUPPORT_HW_RECOVERY)
+                       eError = OSEnableTimer(psDevInfo->hTimer);
+                       if (eError != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SGXPostPowerState : Failed to enable host timer"));
+                               return PVRSRV_ERROR_GENERIC;
+                       }
+#endif
+               }
+
+               PVR_DPF((PVR_DBG_WARNING,
+                        "SGXPostPowerState : SGX Power Transition from %d to %d OK",
+                        eCurrentPowerState, eNewPowerState));
+       }
+
+       return PVRSRV_OK;
+}
+
+static IMG_VOID SGXGetTimingInfo(PVRSRV_SGXDEV_INFO * psDevInfo,
+                                SGX_TIMING_INFORMATION * psSGXTimingInfo)
+{
+       IMG_UINT32 ui32ActivePowManSampleRate;
+
+       psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
+       psDevInfo->ui32uKernelTimerClock =
+           psSGXTimingInfo->ui32CoreClockSpeed /
+           psSGXTimingInfo->ui32uKernelFreq;
+
+#if defined(SUPPORT_HW_RECOVERY)
+       psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
+           psSGXTimingInfo->ui32uKernelFreq /
+           psSGXTimingInfo->ui32HWRecoveryFreq;
+#endif
+
+       ui32ActivePowManSampleRate =
+           psSGXTimingInfo->ui32uKernelFreq *
+           psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+
+       ui32ActivePowManSampleRate += 1;
+
+       psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate =
+           ui32ActivePowManSampleRate;
+}
+
+static PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+                                          IMG_BOOL bIdleDevice)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       SGX_DEVICE_MAP *psSGXDeviceMap;
+
+       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 (bIdleDevice) {
+
+       }
+
+       SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo);
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                "SGXPreClockSpeedChange: SGX clock speed now %luHz",
+                psDevInfo->ui32CoreClockSpeed));
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+                                           IMG_BOOL bIdleDevice)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       if (bIdleDevice) {
+
+       } else {
+               SGXStartTimer(psDevInfo);
+       }
+
+       return PVRSRV_OK;
+}
+
+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);
+                               PDUMPREG(psComm->sWriteHWReg.ui32Offset,
+                                        psComm->sWriteHWReg.ui32Value);
+                               break;
+                       }
+#if defined(PDUMP)
+               case SGX_INIT_OP_PDUMP_HW_REG:
+                       {
+                               PDUMPREG(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_GENERIC;
+                       }
+               }
+
+       }
+
+       return PVRSRV_ERROR_GENERIC;;
+}
+
+static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo,
+                                 IMG_BOOL bHardwareRecovery)
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32ReadOffset, ui32WriteOffset;
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL,
+                    psDevInfo->ui32ClkGateCtl);
+       PDUMPREGWITHFLAGS(EUR_CR_CLKGATECTL, psDevInfo->ui32ClkGateCtl,
+                         PDUMP_FLAGS_CONTINUOUS);
+#if defined(SGX540)
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL2,
+                    psDevInfo->ui32ClkGateCtl2);
+       PDUMPREGWITHFLAGS(EUR_CR_CLKGATECTL2, psDevInfo->ui32ClkGateCtl2,
+                         PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(EUR_CR_POWER)
+#if defined(SGX531)
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
+       PDUMPREG(EUR_CR_POWER, 1);
+#else
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
+       PDUMPREG(EUR_CR_POWER, 0);
+#endif
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MNE_CR_CTRL,
+                    EUR_CR_MNE_CR_CTRL_BYP_CC_MASK);
+       PDUMPREG(EUR_CR_MNE_CR_CTRL, EUR_CR_MNE_CR_CTRL_BYP_CC_MASK);
+#endif
+
+       *psDevInfo->pui32KernelCCBEventKicker = 0;
+#if defined(PDUMP)
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+                sizeof(*psDevInfo->pui32KernelCCBEventKicker),
+                PDUMP_FLAGS_CONTINUOUS,
+                MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+#endif
+
+       psDevInfo->psSGXHostCtl->sTAHWPBDesc.uiAddr = 0;
+       psDevInfo->psSGXHostCtl->s3DHWPBDesc.uiAddr = 0;
+#if defined(PDUMP)
+       PDUMPCOMMENT(" CCB Control - Reset HW PBDesc records");
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                offsetof(PVRSRV_SGX_HOST_CTL, sTAHWPBDesc),
+                sizeof(IMG_DEV_VIRTADDR), PDUMP_FLAGS_CONTINUOUS,
+                MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+                offsetof(PVRSRV_SGX_HOST_CTL, s3DHWPBDesc),
+                sizeof(IMG_DEV_VIRTADDR), PDUMP_FLAGS_CONTINUOUS,
+                MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+       eError =
+           SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommands,
+                        SGX_MAX_INIT_COMMANDS);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SGXInitialise: SGXRunScript failed (%d)", eError));
+               return (PVRSRV_ERROR_GENERIC);
+       }
+
+       SGXStartTimer(psDevInfo);
+
+       if (bHardwareRecovery) {
+               PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
+                   (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
+
+               if (PollForValueKM
+                   ((volatile IMG_UINT32 *)(&psSGXHostCtl->
+                                            ui32InterruptClearFlags), 0,
+                    PVRSRV_USSE_EDM_INTERRUPT_HWR,
+                    MAX_HW_TIME_US / WAIT_TRY_COUNT, 1000) != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "SGXInitialise: Wait for uKernel HW Recovery failed"));
+                       return PVRSRV_ERROR_RETRY;
+               }
+       }
+
+       for (ui32ReadOffset = psDevInfo->psKernelCCBCtl->ui32ReadOffset,
+            ui32WriteOffset = psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+            ui32ReadOffset != ui32WriteOffset;
+            ui32ReadOffset = (ui32ReadOffset + 1) & 0xFF) {
+               *psDevInfo->pui32KernelCCBEventKicker =
+                   (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+               OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_KICK,
+                            EUR_CR_EVENT_KICK_NOW_MASK);
+       }
+
+       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 (PVRSRV_ERROR_GENERIC);
+       }
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DevInitSGXPart1(IMG_VOID * pvDeviceNode)
+{
+       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;
+       IMG_HANDLE hDevInfoOSMemHandle = (IMG_HANDLE) IMG_NULL;
+       PVRSRV_ERROR eError;
+
+       PDUMPCOMMENT("SGX Initialisation Part 1");
+
+       PDUMPCOMMENT("SGX Core Version Information: %s",
+                    SGX_CORE_FRIENDLY_NAME);
+#ifdef SGX_CORE_REV
+       PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
+#else
+       PDUMPCOMMENT("SGX Core Revision Information: head rtl");
+#endif
+
+       if (OSAllocPages
+           (PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_HAP_MULTI_PROCESS |
+            PVRSRV_HAP_CACHED, sizeof(PVRSRV_SGXDEV_INFO),
+            (IMG_VOID **) & psDevInfo, &hDevInfoOSMemHandle) != 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;
+       psDeviceNode->hDeviceOSMemHandle = hDevInfoOSMemHandle;
+
+       psDevInfo->pvDeviceMemoryHeap = (IMG_VOID *) psDeviceMemoryHeap;
+
+       hKernelDevMemContext = BM_CreateContext(psDeviceNode,
+                                               &sPDDevPAddr,
+                                               IMG_NULL, IMG_NULL);
+
+       psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
+
+       for (i = 0; i < psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++) {
+               IMG_HANDLE hDevMemHeap;
+
+               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;
+                       }
+               }
+       }
+
+       eError = MMU_BIFResetPDAlloc(psDevInfo);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevInitSGX : Failed to alloc memory for BIF reset"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       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 PVRSRV_ERROR_GENERIC;
+       }
+
+       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;
+       PVR_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;
+       }
+
+#ifdef SGX_FEATURE_2D_HARDWARE
+       eError = OSCreateResource(&psDevInfo->s2DSlaveportResource);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevInitSGXPart2KM: Failed to create resource !"));
+               return PVRSRV_ERROR_INIT_FAILURE;
+       }
+#endif
+
+       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;
+
+#ifdef SGX_FEATURE_2D_HARDWARE
+
+       if (psSGXDeviceMap->pvSPCpuVBase) {
+               psDevInfo->s2DSlavePortKM.pvData = psSGXDeviceMap->pvSPCpuVBase;
+       } else {
+
+               psDevInfo->s2DSlavePortKM.pvData =
+                   OSMapPhysToLin(psSGXDeviceMap->sSPCpuPBase,
+                                  psSGXDeviceMap->ui32SPSize,
+                                  PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
+                                  IMG_NULL);
+
+               if (!psDevInfo->s2DSlavePortKM.pvData) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "DevInitSGXPart2KM: Failed to map 2D Slave port region\n"));
+                       return PVRSRV_ERROR_BAD_MAPPING;
+               }
+
+       }
+       psDevInfo->s2DSlavePortKM.ui32DataRange = psSGXDeviceMap->ui32SPSize;
+       psDevInfo->s2DSlavePortKM.sPhysBase = psSGXDeviceMap->sSPSysPBase;
+#endif
+
+       SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo);
+
+#if defined (SYS_USING_INTERRUPTS)
+
+       psDeviceNode->pvISRData = psDeviceNode;
+
+       PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
+
+#endif
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+
+       psDevInfo->psSGXHostCtl->ui32PowManFlags |=
+           PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+       eDefaultPowerState = PVRSRV_POWER_STATE_D3;
+#else
+       eDefaultPowerState = PVRSRV_POWER_STATE_D0;
+#endif
+       eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
+                                          SGXPrePowerState, SGXPostPowerState,
+                                          SGXPreClockSpeedChange,
+                                          SGXPostClockSpeedChange,
+                                          (IMG_HANDLE) psDeviceNode,
+                                          PVRSRV_POWER_STATE_D3,
+                                          eDefaultPowerState);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevInitSGXPart2KM: failed to register device with power manager"));
+               return eError;
+       }
+
+       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("Kernel CCB");
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0,
+                sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS,
+                MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
+       PDUMPCOMMENT("Kernel CCB Control");
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0,
+                sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS,
+                MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
+       PDUMPCOMMENT("Kernel CCB Event Kicker");
+       PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+                sizeof(*psDevInfo->pui32KernelCCBEventKicker),
+                PDUMP_FLAGS_CONTINUOUS,
+                MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+
+#if defined(SUPPORT_HW_RECOVERY)
+
+       psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
+                                      1000 * 50 /
+                                      psSGXDeviceMap->sTimingInfo.
+                                      ui32uKernelFreq);
+       if (psDevInfo->hTimer == IMG_NULL) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevInitSGXPart2KM : Failed to register timer callback function"));
+               return PVRSRV_ERROR_GENERIC;
+       }
+#endif
+
+       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;
+       IMG_HANDLE hDevInfoOSMemHandle = psDeviceNode->hDeviceOSMemHandle;
+       PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
+       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
+
+       MMU_BIFResetPDFree(psDevInfo);
+
+       DeinitDevInfo(psDevInfo);
+
+#if defined(SGX_USING_CMD_PROC_LIST)
+       eError =
+           PVRSRVRemoveCmdProcListKM(psDeviceNode->sDevId.ui32DeviceIndex,
+                                     SGX_COMMAND_COUNT);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevDeInitSGX: PVRSRVRemoveCmdProcList failed"));
+               return eError;
+       }
+#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;
+       }
+#ifdef SGX_FEATURE_2D_HARDWARE
+       eError = OSDestroyResource(&psDevInfo->s2DSlaveportResource);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+#endif
+
+       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);
+               }
+       }
+#ifdef SGX_FEATURE_2D_HARDWARE
+
+       if (!psSGXDeviceMap->pvSPCpuVBase) {
+               if (psDevInfo->s2DSlavePortKM.pvData != IMG_NULL) {
+                       OSUnMapPhysToLin(psDevInfo->s2DSlavePortKM.pvData,
+                                        psDevInfo->s2DSlavePortKM.
+                                        ui32DataRange,
+                                        PVRSRV_HAP_KERNEL_ONLY |
+                                        PVRSRV_HAP_UNCACHED, IMG_NULL);
+               }
+       }
+#endif
+
+       OSFreePages(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_HAP_MULTI_PROCESS,
+                   sizeof(PVRSRV_SGXDEV_INFO), psDevInfo, hDevInfoOSMemHandle);
+       psDeviceNode->pvDevice = IMG_NULL;
+
+       if (psDeviceMemoryHeap != IMG_NULL) {
+
+               OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                         sizeof(DEVICE_MEMORY_HEAP_INFO) *
+                         psDeviceNode->sDevMemoryInfo.ui32HeapCount,
+                         psDeviceMemoryHeap, 0);
+       }
+
+       return PVRSRV_OK;
+}
+
+#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;
+       PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
+           (PVRSRV_SGX_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_DPF((PVR_DBG_ERROR,
+                "HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
+
+       PDUMPSUSPEND();
+
+       do {
+               eError = SGXInitialise(psDevInfo, IMG_TRUE);
+       }
+       while (eError == PVRSRV_ERROR_RETRY);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "HWRecoveryResetSGX: SGXInitialise failed (%d)",
+                        eError));
+       }
+
+       PDUMPRESUME();
+
+       PVRSRVPowerUnlock(ui32CallerID);
+
+       SGXScheduleProcessQueues(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;
+       IMG_UINT32 ui32CurrentEDMTasks;
+       IMG_BOOL bLockup = IMG_FALSE;
+       IMG_BOOL bPoweredDown;
+
+       psDevInfo->ui32TimeStamp++;
+
+       bPoweredDown = (IMG_BOOL) ! SGXIsDevicePowered(psDeviceNode);
+
+       if (bPoweredDown) {
+               ui32LockupCounter = 0;
+       } 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;
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SGXOSTimer() detected SGX lockup (0x%x tasks)",
+                                        ui32EDMTasks));
+
+                               bLockup = IMG_TRUE;
+                       }
+               } else {
+                       ui32LockupCounter = 0;
+                       ui32EDMTasks = ui32CurrentEDMTasks;
+                       ui32NumResets = psDevInfo->ui32NumResets;
+               }
+       }
+
+       if (bLockup) {
+               PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
+                   (PVRSRV_SGX_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;
+               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);
+
+               gui32EventStatusServicesByISR = ui32EventStatus;
+
+               ui32EventStatus &= ui32EventEnable;
+
+               if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK) {
+                       ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
+               }
+
+               if (ui32EventClear) {
+                       bInterruptProcessed = IMG_TRUE;
+
+                       ui32EventClear |=
+                           EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
+
+                       OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+                                    EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
+                       //Read back to flush posted write to fix spurious IRQ
+                       OSReadHWReg(psDevInfo->pvRegsBaseKM,
+                                   EUR_CR_EVENT_HOST_CLEAR);
+               }
+       }
+
+       return bInterruptProcessed;
+}
+
+IMG_VOID SGX_MISRHandler(IMG_VOID * pvData)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *) pvData;
+       PVRSRV_SGXDEV_INFO *psDevInfo =
+           (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+       PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
+           (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
+
+       if ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR)
+           && !(psSGXHostCtl->
+                ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR)) {
+               HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+       }
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
+#endif
+}
+#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;
+
+       psDeviceNode->pfnInitDevice = DevInitSGXPart1;
+       psDeviceNode->pfnDeInitDevice = DevDeInitSGX;
+
+       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 (SYS_USING_INTERRUPTS)
+
+       psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
+       psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
+#endif
+
+       psDeviceNode->pfnDeviceCommandComplete = SGXCommandComplete;
+
+       psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+       psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_ADDRESS_SPACE_SIZE;
+
+       psDevMemoryInfo->ui32Flags = 0;
+
+       psDevMemoryInfo->ui32HeapCount = SGX_MAX_HEAP_ID;
+
+       psDevMemoryInfo->ui32SyncHeapID = SGX_SYNCINFO_HEAP_ID;
+
+       psDevMemoryInfo->ui32MappingHeapID = SGX_GENERAL_MAPPING_HEAP_ID;
+
+       if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                      sizeof(DEVICE_MEMORY_HEAP_INFO) *
+                      psDevMemoryInfo->ui32HeapCount,
+                      (IMG_VOID **) & psDevMemoryInfo->psDeviceMemoryHeap,
+                      0) != 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) *
+                psDevMemoryInfo->ui32HeapCount);
+
+       psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+       psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
+       psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_GENERAL_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapSize =
+           SGX_GENERAL_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszName = "General";
+       psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszBSName = "General BS";
+       psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+       psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
+       psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_TADATA_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapSize =
+           SGX_TADATA_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+#if 0
+           | PVRSRV_HAP_KERNEL_ONLY;
+#else
+           | PVRSRV_HAP_MULTI_PROCESS;
+#endif
+       psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszName = "TA Data";
+       psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszBSName = "TA Data BS";
+       psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+       psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
+       psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_KERNEL_CODE_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapSize =
+           SGX_KERNEL_CODE_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+#if 0
+           | PVRSRV_HAP_KERNEL_ONLY;
+#else
+           | PVRSRV_HAP_MULTI_PROCESS;
+#endif
+       psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszName = "Kernel";
+       psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszBSName = "Kernel BS";
+       psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+       psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VIDEO_CODE_HEAP_ID);
+       psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_VIDEO_CODE_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32HeapSize =
+           SGX_VIDEO_CODE_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_KERNEL_ONLY;
+       psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].pszName = "Video";
+       psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].pszBSName = "Video BS";
+       psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_SHARED;
+
+       psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_VIDEO_DATA_HEAP_ID);
+       psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_KERNEL_VIDEO_DATA_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32HeapSize =
+           SGX_KERNEL_VIDEO_DATA_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+#if 0
+           PVRSRV_HAP_KERNEL_ONLY;
+#else
+           PVRSRV_HAP_MULTI_PROCESS;
+#endif
+       psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].pszName =
+           "KernelVideoData";
+       psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].pszBSName =
+           "KernelVideoData BS";
+       psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+       psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
+       psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_PIXELSHADER_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapSize =
+           SGX_PIXELSHADER_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszName = "PixelShaderUSSE";
+       psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszBSName =
+           "PixelShaderUSSE BS";
+       psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+       psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
+       psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_VERTEXSHADER_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapSize =
+           SGX_VERTEXSHADER_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszName =
+           "VertexShaderUSSE";
+       psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszBSName =
+           "VertexShaderUSSE BS";
+       psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+       psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
+       psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapSize =
+           SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszName =
+           "PDSPixelCodeData";
+       psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszBSName =
+           "PDSPixelCodeData BS";
+       psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+       psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
+       psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].sDevVAddrBase.
+           uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapSize =
+           SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszName =
+           "PDSVertexCodeData";
+       psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszBSName =
+           "PDSVertexCodeData BS";
+       psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+       psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
+       psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_SYNCINFO_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapSize =
+           SGX_SYNCINFO_HEAP_SIZE;
+
+       psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszName = "CacheCoherent";
+       psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszBSName = "CacheCoherent BS";
+
+       psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_3DPARAMETERS_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapSize =
+           SGX_3DPARAMETERS_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszName = "3DParameters";
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszBSName =
+           "3DParameters BS";
+#if defined(SUPPORT_PERCONTEXT_PB)
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_PERCONTEXT;
+#else
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+           PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+#endif
+
+       psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
+       psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_GENERAL_MAPPING_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32HeapSize =
+           SGX_GENERAL_MAPPING_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32Attribs =
+           PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
+       psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].pszName =
+           "GeneralMapping";
+       psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].pszBSName =
+           "GeneralMapping BS";
+
+       psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+       psDeviceMemoryHeap[SGX_2D_HEAP_ID].ui32HeapID =
+           HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
+       psDeviceMemoryHeap[SGX_2D_HEAP_ID].sDevVAddrBase.uiAddr =
+           SGX_2D_HEAP_BASE;
+       psDeviceMemoryHeap[SGX_2D_HEAP_ID].ui32HeapSize = SGX_2D_HEAP_SIZE;
+       psDeviceMemoryHeap[SGX_2D_HEAP_ID].ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+           | PVRSRV_MEM_RAM_BACKED_ALLOCATION | PVRSRV_HAP_SINGLE_PROCESS;
+       psDeviceMemoryHeap[SGX_2D_HEAP_ID].pszName = "2D";
+       psDeviceMemoryHeap[SGX_2D_HEAP_ID].pszBSName = "2D BS";
+
+       psDeviceMemoryHeap[SGX_2D_HEAP_ID].DevMemHeapType =
+           DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+#endif
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
+                                   PVR3DIF4_CLIENT_INFO * psClientInfo)
+{
+       PVRSRV_SGXDEV_INFO *psDevInfo =
+           (PVRSRV_SGXDEV_INFO *) ((PVRSRV_DEVICE_NODE *) hDevCookie)->
+           pvDevice;
+
+       psDevInfo->ui32ClientRefCount++;
+#ifdef PDUMP
+       if (psDevInfo->ui32ClientRefCount == 1) {
+               psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
+       }
+#endif
+
+       psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+       OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData,
+                 sizeof(psClientInfo->asDevData));
+
+       return PVRSRV_OK;
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO * psDevInfo,
+                                 SGX_MISC_INFO * psMiscInfo)
+{
+       switch (psMiscInfo->eRequest) {
+       case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
+               {
+                       psMiscInfo->uData.ui32SGXClockSpeed =
+                           psDevInfo->ui32CoreClockSpeed;
+                       return PVRSRV_OK;
+               }
+#ifdef SUPPORT_SGX_HWPERF
+       case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
+               {
+                       psDevInfo->psSGXHostCtl->ui32HWPerfFlags |=
+                           PVRSRV_SGX_HWPERF_ON;
+                       return PVRSRV_OK;
+               }
+       case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
+               {
+                       psDevInfo->psSGXHostCtl->ui32HWPerfFlags &=
+                           ~PVRSRV_SGX_HWPERF_ON;
+                       return PVRSRV_OK;
+               }
+       case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
+               {
+                       SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve =
+                           &psMiscInfo->uData.sRetrieveCB;
+                       PVRSRV_SGX_HWPERF_CB *psHWPerfCB =
+                           (PVRSRV_SGX_HWPERF_CB *) psDevInfo->
+                           psKernelHWPerfCBMemInfo->pvLinAddrKM;
+                       IMG_UINT i = 0;
+
+                       for (;
+                            psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff
+                            && i < psRetrieve->ui32ArraySize; i++) {
+                               PVRSRV_SGX_HWPERF_CBDATA *psData =
+                                   &psHWPerfCB->psHWPerfCBData[psHWPerfCB->
+                                                               ui32Roff];
+                               OSMemCopy(&psRetrieve->psHWPerfData[i], psData,
+                                         sizeof(PVRSRV_SGX_HWPERF_CBDATA));
+                               psRetrieve->psHWPerfData[i].ui32ClockSpeed =
+                                   psDevInfo->ui32CoreClockSpeed;
+                               psRetrieve->psHWPerfData[i].ui32TimeMax =
+                                   psDevInfo->ui32uKernelTimerClock;
+                               psHWPerfCB->ui32Roff =
+                                   (psHWPerfCB->ui32Roff +
+                                    1) & (PVRSRV_SGX_HWPERF_CBSIZE - 1);
+                       }
+                       psRetrieve->ui32DataCount = i;
+                       psRetrieve->ui32Time = OSClockus();
+                       return PVRSRV_OK;
+               }
+#endif
+       default:
+               {
+
+                       return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+       }
+}
+
+#if defined(SUPPORT_SGX_HWPERF)
+IMG_EXPORT
+    PVRSRV_ERROR SGXReadDiffCountersKM(IMG_HANDLE hDevHandle,
+                                      IMG_UINT32 ui32Reg,
+                                      IMG_UINT32 * pui32Old,
+                                      IMG_BOOL bNew,
+                                      IMG_UINT32 ui32New,
+                                      IMG_UINT32 ui32NewReset,
+                                      IMG_UINT32 ui32CountersReg,
+                                      IMG_UINT32 * pui32Time,
+                                      IMG_BOOL * pbActive,
+                                      PVRSRV_SGXDEV_DIFF_INFO * psDiffs)
+{
+       PVRSRV_ERROR eError;
+       SYS_DATA *psSysData;
+       PVRSRV_POWER_DEV *psPowerDevice;
+       IMG_BOOL bPowered = IMG_FALSE;
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       if (bNew) {
+               psDevInfo->ui32HWGroupRequested = ui32New;
+       }
+       psDevInfo->ui32HWReset |= ui32NewReset;
+
+       eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+
+       SysAcquireData(&psSysData);
+
+       psPowerDevice = psSysData->psPowerDeviceList;
+       while (psPowerDevice) {
+               if (psPowerDevice->ui32DeviceIndex ==
+                   psDeviceNode->sDevId.ui32DeviceIndex) {
+                       bPowered =
+                           (IMG_BOOL) (psPowerDevice->eCurrentPowerState ==
+                                       PVRSRV_POWER_STATE_D0);
+                       break;
+               }
+
+               psPowerDevice = psPowerDevice->psNext;
+       }
+
+       *pbActive = bPowered;
+
+       {
+               PVRSRV_SGXDEV_DIFF_INFO sNew, *psPrev = &psDevInfo->sDiffInfo;
+               IMG_UINT32 i;
+
+               sNew.ui32Time[0] = OSClockus();
+
+               *pui32Time = sNew.ui32Time[0];
+
+               if (sNew.ui32Time[0] != psPrev->ui32Time[0] && bPowered) {
+
+                       *pui32Old =
+                           OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
+
+                       for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
+                               sNew.aui32Counters[i] =
+                                   OSReadHWReg(psDevInfo->pvRegsBaseKM,
+                                               ui32CountersReg + (i * 4));
+                       }
+
+                       if (psDevInfo->ui32HWGroupRequested != *pui32Old) {
+
+                               if (psDevInfo->ui32HWReset != 0) {
+                                       OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+                                                    ui32Reg,
+                                                    psDevInfo->
+                                                    ui32HWGroupRequested |
+                                                    psDevInfo->ui32HWReset);
+                                       psDevInfo->ui32HWReset = 0;
+                               }
+
+                               OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg,
+                                            psDevInfo->ui32HWGroupRequested);
+                       }
+
+                       sNew.ui32Marker[0] = psDevInfo->ui32KickTACounter;
+                       sNew.ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
+
+                       sNew.ui32Time[1] =
+                           psDevInfo->psSGXHostCtl->ui32TimeWraps;
+
+                       for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
+                               psDiffs->aui32Counters[i] =
+                                   sNew.aui32Counters[i] -
+                                   psPrev->aui32Counters[i];
+                       }
+
+                       psDiffs->ui32Marker[0] =
+                           sNew.ui32Marker[0] - psPrev->ui32Marker[0];
+                       psDiffs->ui32Marker[1] =
+                           sNew.ui32Marker[1] - psPrev->ui32Marker[1];
+
+                       psDiffs->ui32Time[0] =
+                           sNew.ui32Time[0] - psPrev->ui32Time[0];
+                       psDiffs->ui32Time[1] =
+                           sNew.ui32Time[1] - psPrev->ui32Time[1];
+
+                       *psPrev = sNew;
+               } else {
+
+                       for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
+                               psDiffs->aui32Counters[i] = 0;
+                       }
+
+                       psDiffs->ui32Marker[0] = 0;
+                       psDiffs->ui32Marker[1] = 0;
+
+                       psDiffs->ui32Time[0] = 0;
+                       psDiffs->ui32Time[1] = 0;
+               }
+       }
+
+       PVRSRVPowerUnlock(KERNEL_ID);
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       SGXTestActivePowerEvent(psDeviceNode, KERNEL_ID);
+#endif
+
+       return eError;
+}
+#else
+#endif
diff --git a/pvr/sgxkick.c b/pvr/sgxkick.c
new file mode 100644 (file)
index 0000000..4d192a7
--- /dev/null
@@ -0,0 +1,395 @@
+/**********************************************************************
+ *
+ * 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"
+
+IMG_EXPORT
+    PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle,
+                            PVR3DIF4_CCB_KICK * psCCBKick)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
+           (PVRSRV_KERNEL_MEM_INFO *) psCCBKick->hCCBKernelMemInfo;
+       PVR3DIF4_CMDTA_SHARED *psTACmd;
+       IMG_UINT32 i;
+#if defined(SUPPORT_SGX_HWPERF)
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevHandle;
+       psDevInfo = (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+       if (psCCBKick->bKickRender) {
+               ++psDevInfo->ui32KickTARenderCounter;
+       }
+       ++psDevInfo->ui32KickTACounter;
+#endif
+
+       if (!CCB_OFFSET_IS_VALID
+           (PVR3DIF4_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset)) {
+               PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       psTACmd =
+           CCB_DATA_FROM_OFFSET(PVR3DIF4_CMDTA_SHARED, psCCBMemInfo, psCCBKick,
+                                ui32CCBOffset);
+
+       if (psCCBKick->hTA3DSyncInfo) {
+               psSyncInfo =
+                   (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->hTA3DSyncInfo;
+               psTACmd->sTA3DDependancy.sWriteOpsCompleteDevVAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+               psTACmd->sTA3DDependancy.ui32WriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+               if (psCCBKick->bTADependency) {
+                       psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               }
+       }
+
+       if (psCCBKick->hTASyncInfo != IMG_NULL) {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->hTASyncInfo;
+
+               psTACmd->sTQSyncReadOpsCompleteDevVAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+               psTACmd->sTQSyncWriteOpsCompleteDevVAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+               psTACmd->ui32TQSyncReadOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending++;
+               psTACmd->ui32TQSyncWriteOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+       }
+
+       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;
+       }
+
+       psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
+       if (psCCBKick->ui32NumTAStatusVals != 0) {
+
+               for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           ahTAStatusSyncInfo[i];
+
+                       psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr =
+                           psSyncInfo->sReadOpsCompleteDevVAddr;
+
+                       psTACmd->sCtlTAStatusInfo[i].ui32StatusValue =
+                           psSyncInfo->psSyncData->ui32ReadOpsPending;
+               }
+       }
+
+       psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
+       if (psCCBKick->ui32Num3DStatusVals != 0) {
+
+               for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           ah3DStatusSyncInfo[i];
+
+                       psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr =
+                           psSyncInfo->sReadOpsCompleteDevVAddr;
+
+                       psTACmd->sCtl3DStatusInfo[i].ui32StatusValue =
+                           psSyncInfo->psSyncData->ui32ReadOpsPending;
+               }
+       }
+
+       psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
+       for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
+               psSyncInfo =
+                   (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                   ahSrcKernelSyncInfo[i];
+
+               psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               psTACmd->asSrcSyncs[i].ui32ReadOpPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+               psTACmd->asSrcSyncs[i].ui32WriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+       }
+
+       if (psCCBKick->bFirstKickOrResume
+           && psCCBKick->hRenderSurfSyncInfo != IMG_NULL) {
+               psSyncInfo =
+                   (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->hRenderSurfSyncInfo;
+               psTACmd->sWriteOpsCompleteDevVAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTACmd->sReadOpsCompleteDevVAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+
+               psTACmd->ui32ReadOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+               psTACmd->ui32WriteOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+#if defined(PDUMP)
+               if (PDumpIsCaptureFrameKM()) {
+                       if (psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) {
+
+                               PDUMPCOMMENT("Init render surface last op\r\n");
+
+                               PDUMPMEM(IMG_NULL,
+                                        psSyncInfo->psSyncDataMemInfoKM,
+                                        0,
+                                        sizeof(PVRSRV_SYNC_DATA),
+                                        0,
+                                        MAKEUNIQUETAG(psSyncInfo->
+                                                      psSyncDataMemInfoKM));
+
+                               PDUMPMEM(&psSyncInfo->psSyncData->
+                                        ui32LastOpDumpVal,
+                                        psSyncInfo->psSyncDataMemInfoKM,
+                                        offsetof(PVRSRV_SYNC_DATA,
+                                                 ui32WriteOpsComplete),
+                                        sizeof(psSyncInfo->psSyncData->
+                                               ui32WriteOpsComplete), 0,
+                                        MAKEUNIQUETAG(psSyncInfo->
+                                                      psSyncDataMemInfoKM));
+                       }
+
+                       psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+               }
+#endif
+       }
+#if defined(PDUMP)
+       if (PDumpIsCaptureFrameKM()) {
+               PDUMPCOMMENT("Shared part of TA command\r\n");
+
+               PDUMPMEM(psTACmd,
+                        psCCBMemInfo,
+                        psCCBKick->ui32CCBDumpWOff,
+                        sizeof(PVR3DIF4_CMDTA_SHARED),
+                        0, MAKEUNIQUETAG(psCCBMemInfo));
+
+               if (psCCBKick->hRenderSurfSyncInfo != IMG_NULL) {
+                       IMG_UINT32 ui32HackValue;
+
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           hRenderSurfSyncInfo;
+                       ui32HackValue =
+                           psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+                       PDUMPCOMMENT
+                           ("Hack render surface last op in TA cmd\r\n");
+
+                       PDUMPMEM(&ui32HackValue,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_CMDTA_SHARED,
+                                         ui32WriteOpsPendingVal),
+                                sizeof(IMG_UINT32), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+
+                       ui32HackValue = 0;
+                       PDUMPCOMMENT
+                           ("Hack render surface read op in TA cmd\r\n");
+
+                       PDUMPMEM(&ui32HackValue,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_CMDTA_SHARED,
+                                         sReadOpsCompleteDevVAddr),
+                                sizeof(IMG_UINT32), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+               }
+
+               for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           ahTAStatusSyncInfo[i];
+
+                       PDUMPCOMMENT("Hack TA status value in TA cmd\r\n");
+
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_CMDTA_SHARED,
+                                         sCtlTAStatusInfo[i].ui32StatusValue),
+                                sizeof(IMG_UINT32), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+               }
+
+               for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           ah3DStatusSyncInfo[i];
+
+                       PDUMPCOMMENT("Hack 3D status value in TA cmd\r\n");
+
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                psCCBMemInfo,
+                                psCCBKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_CMDTA_SHARED,
+                                         sCtl3DStatusInfo[i].ui32StatusValue),
+                                sizeof(IMG_UINT32), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+               }
+       }
+#endif
+
+       eError =
+           SGXScheduleCCBCommandKM(hDevHandle, psCCBKick->eCommand,
+                                   &psCCBKick->sCommand, KERNEL_ID);
+       if (eError == PVRSRV_ERROR_RETRY) {
+               if (psCCBKick->bFirstKickOrResume
+                   && psCCBKick->hRenderSurfSyncInfo != IMG_NULL) {
+
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           hRenderSurfSyncInfo;
+                       psSyncInfo->psSyncData->ui32WriteOpsPending--;
+               }
+
+               for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           ahSrcKernelSyncInfo[i];
+                       psSyncInfo->psSyncData->ui32ReadOpsPending--;
+               }
+
+#if defined(PDUMP)
+               if (psCCBKick->bFirstKickOrResume
+                   && psCCBKick->hRenderSurfSyncInfo != IMG_NULL) {
+                       if (PDumpIsCaptureFrameKM()) {
+                               psSyncInfo =
+                                   (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                                   hRenderSurfSyncInfo;
+                               psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+                       }
+               }
+#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++) {
+               psSyncInfo =
+                   (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                   ahTAStatusSyncInfo[i];
+
+               psSyncInfo->psSyncData->ui32ReadOpsComplete =
+                   psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+       }
+
+       for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
+               psSyncInfo =
+                   (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                   ahSrcKernelSyncInfo[i];
+
+               psSyncInfo->psSyncData->ui32ReadOpsComplete =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+       }
+
+       if (psCCBKick->bTerminateOrAbort) {
+               if (psCCBKick->hRenderSurfSyncInfo != IMG_NULL) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           hRenderSurfSyncInfo;
+                       psSyncInfo->psSyncData->ui32WriteOpsComplete =
+                           psCCBKick->bFirstKickOrResume ? psSyncInfo->
+                           psSyncData->ui32WriteOpsPending : (psCCBKick->
+                                                              ui32WriteOpsPendingVal
+                                                              + 1);
+               }
+
+               for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->
+                           ah3DStatusSyncInfo[i];
+
+                       psSyncInfo->psSyncData->ui32ReadOpsComplete =
+                           psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+               }
+       }
+#endif
+
+       return eError;
+}
diff --git a/pvr/sgxmmu.h b/pvr/sgxmmu.h
new file mode 100644 (file)
index 0000000..8e688bf
--- /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 
+ *
+ ******************************************************************************/
+
+#if !defined(__SGXMMU_KM_H__)
+#define __SGXMMU_KM_H__
+
+#define SGX_MMU_PAGE_SHIFT                             (12)
+#define SGX_MMU_PAGE_SIZE                              (1UL<<SGX_MMU_PAGE_SHIFT)
+#define SGX_MMU_PAGE_MASK                              (SGX_MMU_PAGE_SIZE - 1UL)
+
+#define SGX_MMU_PD_SHIFT                               (10)
+#define SGX_MMU_PD_SIZE                                        (1UL<<SGX_MMU_PD_SHIFT)
+#define SGX_MMU_PD_MASK                                        (0xFFC00000UL)
+
+#define SGX_MMU_PDE_ADDR_MASK                  (0xFFFFF000UL)
+#define SGX_MMU_PDE_VALID                              (0x00000001UL)
+#define SGX_MMU_PDE_WRITEONLY                  (0x00000002UL)
+#define SGX_MMU_PDE_READONLY                   (0x00000004UL)
+#define SGX_MMU_PDE_CACHECONSISTENT            (0x00000008UL)
+#define SGX_MMU_PDE_EDMPROTECT                 (0x00000010UL)
+
+#define SGX_MMU_PT_SHIFT                               (10)
+#define SGX_MMU_PT_SIZE                                        (1UL<<SGX_MMU_PT_SHIFT)
+#define SGX_MMU_PT_MASK                                        (0x003FF000UL)
+
+#define SGX_MMU_PTE_ADDR_MASK                  (0xFFFFF000UL)
+#define SGX_MMU_PTE_VALID                              (0x00000001UL)
+#define SGX_MMU_PTE_WRITEONLY                  (0x00000002UL)
+#define SGX_MMU_PTE_READONLY                   (0x00000004UL)
+#define SGX_MMU_PTE_CACHECONSISTENT            (0x00000008UL)
+#define SGX_MMU_PTE_EDMPROTECT                 (0x00000010UL)
+
+#endif
diff --git a/pvr/sgxreset.c b/pvr/sgxreset.c
new file mode 100644 (file)
index 0000000..345ce08
--- /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 
+ *
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+
+#include "pdump_km.h"
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define SGX_BIF_DIR_LIST_INDEX_EDM     15
+#define SGX_BIF_DIR_LIST_REG_EDM       EUR_CR_BIF_DIR_LIST_BASE15
+#else
+#define SGX_BIF_DIR_LIST_REG_EDM       EUR_CR_BIF_DIR_LIST_BASE0
+#endif
+
+static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO * psDevInfo,
+                                 IMG_BOOL bResetBIF,
+                                 IMG_UINT32 ui32PDUMPFlags, IMG_BOOL bPDump)
+{
+#if !defined(SGX540)
+       IMG_UINT32 ui32SoftResetRegVal =
+#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
+           EUR_CR_SOFT_RESET_TWOD_RESET_MASK |
+#endif
+           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;
+#else
+       IMG_UINT32 ui32SoftResetRegVal =
+           EUR_CR_SOFT_RESET_VDM_RESET_MASK |
+           EUR_CR_SOFT_RESET_DPM_RESET_MASK |
+           EUR_CR_SOFT_RESET_TE_RESET_MASK |
+           EUR_CR_SOFT_RESET_MTE_RESET_MASK |
+           EUR_CR_SOFT_RESET_ISP_RESET_MASK |
+           EUR_CR_SOFT_RESET_ISP2_RESET_MASK |
+           EUR_CR_SOFT_RESET_TSP_RESET_MASK |
+           EUR_CR_SOFT_RESET_PDS_RESET_MASK |
+           EUR_CR_SOFT_RESET_PBE_RESET_MASK |
+           EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK |
+           EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK |
+           EUR_CR_SOFT_RESET_MADD_RESET_MASK |
+           EUR_CR_SOFT_RESET_ITR_RESET_MASK |
+           EUR_CR_SOFT_RESET_TEX_RESET_MASK |
+           EUR_CR_SOFT_RESET_USE_RESET_MASK |
+           EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK |
+           EUR_CR_SOFT_RESET_TA_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(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(1000 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+       if (bPDump) {
+               PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
+#if defined(PDUMP)
+               PDumpRegRead(EUR_CR_SOFT_RESET, ui32PDUMPFlags);
+#endif
+       }
+
+}
+
+static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO * psDevInfo,
+                               IMG_UINT32 ui32PDUMPFlags, IMG_BOOL bPDump)
+{
+       IMG_UINT32 ui32RegVal;
+
+       ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+       if (bPDump) {
+               PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+       }
+       SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+       ui32RegVal = 0;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+       if (bPDump) {
+               PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+       }
+       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 / WAIT_TRY_COUNT,
+                    WAIT_TRY_COUNT) != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "Wait for DC invalidate failed."));
+               }
+
+               if (bPDump) {
+                       PDUMPREGPOLWITHFLAGS(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_UINT32 ui32PDUMPFlags)
+{
+       IMG_UINT32 ui32RegVal;
+
+       const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+       IMG_UINT32 ui32BIFCtrl;
+#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
+       IMG_UINT32 ui32BIFMemArb;
+#endif
+#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(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(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(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_MULTIPLE_MEM_CONTEXTS)
+       ui32RegVal = 0;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK_SET, ui32RegVal);
+       PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+       PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
+
+       ui32BIFMemArb = (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,
+                    ui32BIFMemArb);
+       PDUMPREGWITHFLAGS(EUR_CR_BIF_MEM_ARB_CONFIG, ui32BIFMemArb,
+                         ui32PDUMPFlags);
+#endif
+#endif
+
+       ui32RegVal = 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_VALID;
+               psDevInfo->pui32BIFResetPT[ui32PTIndex] =
+                   psDevInfo->sBIFResetPageDevPAddr.uiAddr | 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;
+       }
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+       ui32BIFCtrl =
+           (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
+#ifdef SGX_FEATURE_2D_HARDWARE
+
+       ui32BIFCtrl |=
+           (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
+#endif
+#if defined(FIX_HW_BRN_23410)
+
+       ui32BIFCtrl |=
+           (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
+#endif
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32BIFCtrl);
+       PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK0, ui32BIFCtrl, ui32PDUMPFlags);
+#endif
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_BIF_DIR_LIST_REG_EDM,
+                    psDevInfo->sKernelPDDevPAddr.uiAddr);
+       PDUMPPDREGWITHFLAGS(SGX_BIF_DIR_LIST_REG_EDM,
+                           psDevInfo->sKernelPDDevPAddr.uiAddr, ui32PDUMPFlags,
+                           PDUMP_PD_UNIQUETAG);
+
+#ifdef SGX_FEATURE_2D_HARDWARE
+
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE,
+                    SGX_2D_HEAP_BASE);
+       PDUMPREGWITHFLAGS(EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE,
+                         ui32PDUMPFlags);
+#endif
+
+       SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+       PVR_DPF((PVR_DBG_WARNING, "Soft Reset of SGX"));
+       SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+       ui32RegVal = 0;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
+       PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+       SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+       PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
+}
diff --git a/pvr/sgxscript.h b/pvr/sgxscript.h
new file mode 100644 (file)
index 0000000..cccf28a
--- /dev/null
@@ -0,0 +1,70 @@
+/**********************************************************************
+ *
+ * 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
+       } SGX_INIT_COMMAND;
+
+       typedef struct _SGX_INIT_SCRIPTS_ {
+               SGX_INIT_COMMAND asInitCommands[SGX_MAX_INIT_COMMANDS];
+               SGX_INIT_COMMAND asDeinitCommands[SGX_MAX_DEINIT_COMMANDS];
+       } SGX_INIT_SCRIPTS;
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/sgxtransfer.c b/pvr/sgxtransfer.c
new file mode 100644 (file)
index 0000000..df8d84a
--- /dev/null
@@ -0,0 +1,514 @@
+/**********************************************************************
+ *
+ * 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"
+
+IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle,
+                                           PVRSRV_TRANSFER_SGX_KICK * psKick)
+{
+       PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
+           (PVRSRV_KERNEL_MEM_INFO *) psKick->hCCBMemInfo;
+       PVRSRV_SGX_COMMAND sCommand = { 0 };
+       PVR3DIF4_TRANSFERCMD_SHARED *psTransferCmd;
+       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       IMG_UINT32 i;
+       PVRSRV_ERROR eError;
+
+       if (!CCB_OFFSET_IS_VALID
+           (PVR3DIF4_TRANSFERCMD_SHARED, psCCBMemInfo, psKick,
+            ui32SharedCmdCCBOffset)) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SGXSubmitTransferKM: Invalid CCB offset"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       psTransferCmd =
+           CCB_DATA_FROM_OFFSET(PVR3DIF4_TRANSFERCMD_SHARED, psCCBMemInfo,
+                                psKick, ui32SharedCmdCCBOffset);
+
+       if (psTransferCmd->ui32NumStatusVals > SGXTQ_MAX_STATUS) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (psKick->ui32StatusFirstSync +
+           (psKick->ui32NumSrcSync ? (psKick->ui32NumSrcSync - 1) : 0) +
+           (psKick->ui32NumDstSync ? (psKick->ui32NumDstSync - 1) : 0) >
+           psTransferCmd->ui32NumStatusVals) {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (psKick->hTASyncInfo != IMG_NULL) {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psKick->hTASyncInfo;
+
+               psTransferCmd->ui32TASyncWriteOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               psTransferCmd->ui32TASyncReadOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psTransferCmd->sTASyncWriteOpsCompleteDevVAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTransferCmd->sTASyncReadOpsCompleteDevVAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+       } else {
+               psTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+               psTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+       }
+
+       if (psKick->h3DSyncInfo != IMG_NULL) {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psKick->h3DSyncInfo;
+
+               psTransferCmd->ui323DSyncWriteOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               psTransferCmd->ui323DSyncReadOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psTransferCmd->s3DSyncWriteOpsCompleteDevVAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTransferCmd->s3DSyncReadOpsCompleteDevVAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+       } else {
+               psTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+               psTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+       }
+
+       psTransferCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
+       psTransferCmd->ui32NumDstSync = psKick->ui32NumDstSync;
+
+       if (psKick->ui32NumSrcSync > 0) {
+               psSyncInfo =
+                   (PVRSRV_KERNEL_SYNC_INFO *) psKick->ahSrcSyncInfo[0];
+
+               psTransferCmd->ui32SrcWriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+               psTransferCmd->ui32SrcReadOpPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psTransferCmd->sSrcWriteOpsCompleteDevAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTransferCmd->sSrcReadOpsCompleteDevAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+       }
+       if (psKick->ui32NumDstSync > 0) {
+               psSyncInfo =
+                   (PVRSRV_KERNEL_SYNC_INFO *) psKick->ahDstSyncInfo[0];
+
+               psTransferCmd->ui32DstWriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+               psTransferCmd->ui32DstReadOpPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psTransferCmd->sDstWriteOpsCompleteDevAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTransferCmd->sDstReadOpsCompleteDevAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+       }
+
+       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 (psKick->ui32NumSrcSync > 1) {
+               for (i = 1; i < psKick->ui32NumSrcSync; i++) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psKick->
+                           ahSrcSyncInfo[i];
+
+                       psTransferCmd->sCtlStatusInfo[psKick->
+                                                     ui32StatusFirstSync].
+                           ui32StatusValue =
+                           psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+                       psTransferCmd->sCtlStatusInfo[psKick->
+                                                     ui32StatusFirstSync].
+                           sStatusDevAddr =
+                           psSyncInfo->sReadOpsCompleteDevVAddr;
+
+                       psKick->ui32StatusFirstSync++;
+               }
+       }
+
+       if (psKick->ui32NumDstSync > 1) {
+               for (i = 1; i < psKick->ui32NumDstSync; i++) {
+                       psSyncInfo =
+                           (PVRSRV_KERNEL_SYNC_INFO *) psKick->
+                           ahDstSyncInfo[i];
+
+                       psTransferCmd->sCtlStatusInfo[psKick->
+                                                     ui32StatusFirstSync].
+                           ui32StatusValue =
+                           psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+                       psTransferCmd->sCtlStatusInfo[psKick->
+                                                     ui32StatusFirstSync].
+                           sStatusDevAddr =
+                           psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+                       psKick->ui32StatusFirstSync++;
+               }
+       }
+#if defined(PDUMP)
+       if (PDumpIsCaptureFrameKM()) {
+               PDUMPCOMMENT("Shared part of transfer command\r\n");
+               PDUMPMEM(psTransferCmd,
+                        psCCBMemInfo,
+                        psKick->ui32CCBDumpWOff,
+                        sizeof(PVR3DIF4_TRANSFERCMD_SHARED),
+                        0, MAKEUNIQUETAG(psCCBMemInfo));
+
+               if (psKick->ui32NumSrcSync > 0) {
+                       psSyncInfo = psKick->ahSrcSyncInfo[0];
+
+                       PDUMPCOMMENT
+                           ("Hack src surface write op in transfer cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                psCCBMemInfo,
+                                psKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_TRANSFERCMD_SHARED,
+                                         ui32SrcWriteOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT
+                           ("Hack src surface read op in transfer cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                psCCBMemInfo,
+                                psKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_TRANSFERCMD_SHARED,
+                                         ui32SrcReadOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastReadOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+               }
+               if (psKick->ui32NumDstSync > 0) {
+                       psSyncInfo = psKick->ahDstSyncInfo[0];
+
+                       PDUMPCOMMENT
+                           ("Hack dest surface write op in transfer cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                psCCBMemInfo,
+                                psKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_TRANSFERCMD_SHARED,
+                                         ui32DstWriteOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT
+                           ("Hack dest surface read op in transfer cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                psCCBMemInfo,
+                                psKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_TRANSFERCMD_SHARED,
+                                         ui32DstReadOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastReadOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+               }
+
+               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
+
+       sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_TRANSFERCMD;
+       sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+
+       eError =
+           SGXScheduleCCBCommandKM(hDevHandle, PVRSRV_SGX_COMMAND_EDM_KICK,
+                                   &sCommand, KERNEL_ID);
+
+#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;
+       }
+
+       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;
+       PVRSRV_SGX_COMMAND sCommand = { 0 };
+       PVR3DIF4_2DCMD_SHARED *ps2DCmd;
+       PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 i;
+
+       if (!CCB_OFFSET_IS_VALID
+           (PVR3DIF4_2DCMD_SHARED, psCCBMemInfo, psKick,
+            ui32SharedCmdCCBOffset)) {
+               PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       ps2DCmd =
+           CCB_DATA_FROM_OFFSET(PVR3DIF4_2DCMD_SHARED, psCCBMemInfo, psKick,
+                                ui32SharedCmdCCBOffset);
+
+       OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd));
+
+       if (psKick->hTASyncInfo != IMG_NULL) {
+               psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psKick->hTASyncInfo;
+
+               ps2DCmd->sTASyncData.ui32WriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               ps2DCmd->sTASyncData.ui32ReadOpPendingVal =
+                   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.ui32WriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               ps2DCmd->s3DSyncData.ui32ReadOpPendingVal =
+                   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].ui32WriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+               ps2DCmd->sSrcSyncData[i].ui32ReadOpPendingVal =
+                   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.ui32WriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+               ps2DCmd->sDstSyncData.ui32ReadOpPendingVal =
+                   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()) {
+
+               PDUMPCOMMENT("Shared part of 2D command\r\n");
+               PDUMPMEM(ps2DCmd,
+                        psCCBMemInfo,
+                        psKick->ui32CCBDumpWOff,
+                        sizeof(PVR3DIF4_2DCMD_SHARED),
+                        0, 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(PVR3DIF4_2DCMD_SHARED,
+                                         sSrcSyncData[i].
+                                         ui32WriteOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                psCCBMemInfo,
+                                psKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_2DCMD_SHARED,
+                                         sSrcSyncData[i].ui32ReadOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastReadOpDumpVal), 0,
+                                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(PVR3DIF4_2DCMD_SHARED,
+                                         sDstSyncData.ui32WriteOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                psCCBMemInfo,
+                                psKick->ui32CCBDumpWOff +
+                                offsetof(PVR3DIF4_2DCMD_SHARED,
+                                         sDstSyncData.ui32ReadOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastReadOpDumpVal), 0,
+                                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[0] = PVRSRV_CCBFLAGS_2DCMD;
+       sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr;
+
+       eError =
+           SGXScheduleCCBCommandKM(hDevHandle, PVRSRV_SGX_COMMAND_EDM_KICK,
+                                   &sCommand, KERNEL_ID);
+
+#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;
+       }
+
+       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/pvr/sgxutils.c b/pvr/sgxutils.c
new file mode 100644 (file)
index 0000000..47ee31e
--- /dev/null
@@ -0,0 +1,915 @@
+/**********************************************************************
+ *
+ * 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 "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.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/tty.h>
+#else
+#include <stdio.h>
+#endif
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+PVRSRV_ERROR SysPowerDownMISR(IMG_UINT32 ui32DeviceIndex,
+                             IMG_UINT32 ui32CallerID);
+#endif
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+IMG_BOOL gbPowerUpPDumped = IMG_FALSE;
+
+IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode,
+                                IMG_UINT32 ui32CallerID)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_SGX_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+       if ((psSGXHostCtl->
+            ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER)
+           && !(psSGXHostCtl->
+                ui32PowManFlags & PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST)) {
+
+               {
+
+                       PDUMPSUSPEND();
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+
+                       eError =
+                           SysPowerDownMISR(psDeviceNode->sDevId.
+                                            ui32DeviceIndex, ui32CallerID);
+#else
+                       eError =
+                           PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.
+                                                       ui32DeviceIndex,
+                                                       PVRSRV_POWER_STATE_D3,
+                                                       ui32CallerID,
+                                                       IMG_FALSE);
+                       if (eError == PVRSRV_OK) {
+
+                               psSGXHostCtl->ui32NumActivePowerEvents++;
+
+                               if ((*(volatile IMG_UINT32 *)
+                                    (&psSGXHostCtl->ui32PowManFlags)
+                                    &
+                                    PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE)
+                                   != 0) {
+
+                                       if (ui32CallerID == ISR_ID) {
+                                               psDeviceNode->
+                                                   bReProcessDeviceCommandComplete
+                                                   = IMG_TRUE;
+                                       } else {
+                                               SGXScheduleProcessQueues
+                                                   (psDeviceNode);
+                                       }
+                               }
+                       }
+#endif
+                       if (eError == PVRSRV_ERROR_RETRY) {
+
+                               eError = PVRSRV_OK;
+                       }
+
+                       PDUMPRESUME();
+               }
+       }
+
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%lu",
+                        eError));
+       }
+}
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGXAcquireKernelCCBSlot)
+#endif
+static INLINE PVRSRV_SGX_COMMAND *SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *
+                                                         psCCB)
+{
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0;
+
+       do {
+               if (((*psCCB->pui32WriteOffset + 1) & 255) !=
+                   *psCCB->pui32ReadOffset) {
+                       return &psCCB->psCommands[*psCCB->pui32WriteOffset];
+               }
+
+               if (bStart == IMG_FALSE) {
+                       bStart = IMG_TRUE;
+                       uiStart = OSClockus();
+               }
+               OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+       } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+
+       return IMG_NULL;
+}
+
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE * psDeviceNode,
+                                    PVRSRV_SGX_COMMAND_TYPE eCommandType,
+                                    PVRSRV_SGX_COMMAND * psCommandData,
+                                    IMG_UINT32 ui32CallerID)
+{
+       PVRSRV_SGX_CCB_INFO *psKernelCCB;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_SGXDEV_INFO *psDevInfo;
+       PVRSRV_SGX_COMMAND *psSGXCommand;
+#if defined(PDUMP)
+       IMG_VOID *pvDumpCommand;
+#endif
+
+       psDevInfo = (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+       psKernelCCB = psDevInfo->psKernelCCBInfo;
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       {
+               if (ui32CallerID == ISR_ID || gbPowerUpPDumped) {
+                       PDUMPSUSPEND();
+               }
+
+               eError =
+                   PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.
+                                               ui32DeviceIndex,
+                                               PVRSRV_POWER_STATE_D0,
+                                               ui32CallerID, IMG_TRUE);
+
+               if (ui32CallerID == ISR_ID || gbPowerUpPDumped) {
+                       PDUMPRESUME();
+               } else if (eError == PVRSRV_OK) {
+                       gbPowerUpPDumped = IMG_TRUE;
+               }
+       }
+#else
+
+       eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+#endif
+
+       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:%ld eError:%lu", ui32CallerID,
+                                eError));
+               }
+
+               return eError;
+       }
+
+       psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
+
+       if (!psSGXCommand) {
+               eError = PVRSRV_ERROR_TIMEOUT;
+               goto Exit;
+       }
+
+       psCommandData->ui32Data[2] = psDevInfo->ui32CacheControl;
+
+#if defined(PDUMP)
+
+       psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
+#endif
+
+       psDevInfo->ui32CacheControl = 0;
+
+       *psSGXCommand = *psCommandData;
+
+       switch (eCommandType) {
+       case PVRSRV_SGX_COMMAND_EDM_KICK:
+               psSGXCommand->ui32ServiceAddress = psDevInfo->ui32TAKickAddress;
+               break;
+       case PVRSRV_SGX_COMMAND_VIDEO_KICK:
+               psSGXCommand->ui32ServiceAddress =
+                   psDevInfo->ui32VideoHandlerAddress;
+               break;
+       default:
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SGXScheduleCCBCommandKM: Unknown command type: %d",
+                        eCommandType));
+               eError = PVRSRV_ERROR_GENERIC;
+               goto Exit;
+       }
+
+#if defined(PDUMP)
+       if (ui32CallerID != ISR_ID) {
+
+               PDUMPCOMMENTWITHFLAGS(0,
+                                     "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, IMG_FALSE, IMG_FALSE,
+                           MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+
+               PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB command\r\n");
+               pvDumpCommand =
+                   (IMG_VOID *) ((IMG_UINT8 *) psKernelCCB->psCCBMemInfo->
+                                 pvLinAddrKM +
+                                 (*psKernelCCB->pui32WriteOffset *
+                                  sizeof(PVRSRV_SGX_COMMAND)));
+
+               PDUMPMEM(pvDumpCommand,
+                        psKernelCCB->psCCBMemInfo,
+                        psKernelCCB->ui32CCBDumpWOff *
+                        sizeof(PVRSRV_SGX_COMMAND), sizeof(PVRSRV_SGX_COMMAND),
+                        0, MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+               PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
+                        psKernelCCB->psCCBMemInfo,
+                        psKernelCCB->ui32CCBDumpWOff *
+                        sizeof(PVRSRV_SGX_COMMAND) +
+                        offsetof(PVRSRV_SGX_COMMAND, ui32Data[2]),
+                        sizeof(IMG_UINT32), 0,
+                        MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+               if (PDumpIsCaptureFrameKM()) {
+
+                       psDevInfo->sPDContext.ui32CacheControl = 0;
+               }
+       }
+#endif
+
+       *psKernelCCB->pui32WriteOffset =
+           (*psKernelCCB->pui32WriteOffset + 1) & 255;
+
+#if defined(PDUMP)
+       if (ui32CallerID != ISR_ID) {
+               if (PDumpIsCaptureFrameKM()) {
+                       psKernelCCB->ui32CCBDumpWOff =
+                           (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
+               }
+
+               PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB write offset\r\n");
+               PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+                        psKernelCCB->psCCBCtlMemInfo,
+                        offsetof(PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
+                        sizeof(IMG_UINT32),
+                        0, MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+               PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB event kicker\r\n");
+               PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+                        psDevInfo->psKernelCCBEventKickerMemInfo,
+                        0,
+                        sizeof(IMG_UINT32),
+                        0,
+                        MAKEUNIQUETAG(psDevInfo->
+                                      psKernelCCBEventKickerMemInfo));
+               PDUMPCOMMENTWITHFLAGS(0, "Event kick\r\n");
+               PDUMPREGWITHFLAGS(EUR_CR_EVENT_KICK, EUR_CR_EVENT_KICK_NOW_MASK,
+                                 0);
+       }
+#endif
+
+       *psDevInfo->pui32KernelCCBEventKicker =
+           (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+       OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_KICK,
+                    EUR_CR_EVENT_KICK_NOW_MASK);
+
+#if defined(NO_HARDWARE)
+
+       *psKernelCCB->pui32ReadOffset =
+           (*psKernelCCB->pui32ReadOffset + 1) & 255;
+#endif
+
+Exit:
+       PVRSRVPowerUnlock(ui32CallerID);
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       if (ui32CallerID != ISR_ID) {
+
+               SGXTestActivePowerEvent(psDeviceNode, ui32CallerID);
+       }
+#endif
+
+       return eError;
+}
+
+IMG_VOID SGXScheduleProcessQueues(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_SGX_HOST_CTL *psHostCtl =
+           psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+       IMG_UINT32 ui32PowManFlags;
+       PVRSRV_SGX_COMMAND sCommand = { 0 };
+
+       ui32PowManFlags = psHostCtl->ui32PowManFlags;
+       if ((ui32PowManFlags & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0) {
+
+               return;
+       }
+
+       sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD;
+       eError =
+           SGXScheduleCCBCommandKM(psDeviceNode, PVRSRV_SGX_COMMAND_EDM_KICK,
+                                   &sCommand, ISR_ID);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SGXScheduleProcessQueues failed to schedule CCB command: %lu",
+                        eError));
+       }
+}
+
+#if defined (PDUMP)
+IMG_VOID DumpBufferArray(PPVR3DIF4_KICKTA_DUMP_BUFFER psBufferArray,
+                        IMG_UINT32 ui32BufferArrayLength, IMG_BOOL bDumpPolls)
+{
+       IMG_UINT32 i;
+
+       for (i = 0; i < ui32BufferArrayLength; i++) {
+               PPVR3DIF4_KICKTA_DUMP_BUFFER psBuffer;
+               PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+               IMG_CHAR *pszName;
+               IMG_HANDLE hUniqueTag;
+
+               psBuffer = &psBufferArray[i];
+               pszName = psBuffer->pszName;
+               if (!pszName) {
+                       pszName = "Nameless buffer";
+               }
+
+               hUniqueTag =
+                   MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *) psBuffer->
+                                 hKernelMemInfo);
+               psSyncInfo =
+                   ((PVRSRV_KERNEL_MEM_INFO *) psBuffer->hKernelMemInfo)->
+                   psKernelSyncInfo;
+
+               if (psBuffer->ui32Start <= psBuffer->ui32End) {
+                       if (bDumpPolls) {
+                               PDUMPCOMMENTWITHFLAGS(0,
+                                                     "Wait for %s space\r\n",
+                                                     pszName);
+                               PDUMPCBP(psSyncInfo->psSyncDataMemInfoKM,
+                                        offsetof(PVRSRV_SYNC_DATA,
+                                                 ui32ReadOpsComplete),
+                                        psBuffer->ui32Start,
+                                        psBuffer->ui32SpaceUsed,
+                                        psBuffer->ui32BufferSize, 0,
+                                        MAKEUNIQUETAG(psSyncInfo->
+                                                      psSyncDataMemInfoKM));
+                       }
+
+                       PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName);
+                       PDUMPMEM(NULL,
+                                (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(psSyncInfo->psSyncDataMemInfoKM,
+                                        offsetof(PVRSRV_SYNC_DATA,
+                                                 ui32ReadOpsComplete),
+                                        psBuffer->ui32Start,
+                                        psBuffer->ui32BackEndLength,
+                                        psBuffer->ui32BufferSize, 0,
+                                        MAKEUNIQUETAG(psSyncInfo->
+                                                      psSyncDataMemInfoKM));
+                       }
+                       PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName);
+                       PDUMPMEM(NULL,
+                                (PVRSRV_KERNEL_MEM_INFO *) psBuffer->
+                                hKernelMemInfo, psBuffer->ui32Start,
+                                psBuffer->ui32BackEndLength, 0, hUniqueTag);
+
+                       if (bDumpPolls) {
+                               PDUMPMEMPOL(psSyncInfo->psSyncDataMemInfoKM,
+                                           offsetof(PVRSRV_SYNC_DATA,
+                                                    ui32ReadOpsComplete), 0,
+                                           0xFFFFFFFF,
+                                           PDUMP_POLL_OPERATOR_NOTEQUAL,
+                                           IMG_FALSE, IMG_FALSE,
+                                           MAKEUNIQUETAG(psSyncInfo->
+                                                         psSyncDataMemInfoKM));
+
+                               PDUMPCOMMENTWITHFLAGS(0,
+                                                     "Wait for %s space\r\n",
+                                                     pszName);
+                               PDUMPCBP(psSyncInfo->psSyncDataMemInfoKM,
+                                        offsetof(PVRSRV_SYNC_DATA,
+                                                 ui32ReadOpsComplete), 0,
+                                        psBuffer->ui32End,
+                                        psBuffer->ui32BufferSize, 0,
+                                        MAKEUNIQUETAG(psSyncInfo->
+                                                      psSyncDataMemInfoKM));
+                       }
+                       PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName);
+                       PDUMPMEM(NULL,
+                                (PVRSRV_KERNEL_MEM_INFO *) psBuffer->
+                                hKernelMemInfo, 0, psBuffer->ui32End, 0,
+                                hUniqueTag);
+               }
+       }
+}
+#endif
+
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+       return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+                                        PVR3DIF4_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->hCtlKernelMemInfoHandle =
+           (IMG_HANDLE) psDevInfo->psKernelSGXHostCtlMemInfo;
+
+       return PVRSRV_OK;
+}
+
+static IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE * psDeviceNode,
+                                 IMG_DEV_VIRTADDR * psHWDataDevVAddr,
+                                 IMG_UINT32 ui32ResManRequestFlag)
+{
+       PVRSRV_SGXDEV_INFO *psSGXDevInfo =
+           (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+       PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo =
+           psSGXDevInfo->psKernelSGXHostCtlMemInfo;
+       PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
+           (PVRSRV_SGX_HOST_CTL *) psSGXHostCtlMemInfo->pvLinAddrKM;
+       IMG_UINT32 ui32PowManFlags;
+#if defined (PDUMP)
+       IMG_HANDLE hUniqueTag = MAKEUNIQUETAG(psSGXHostCtlMemInfo);
+#endif
+
+       ui32PowManFlags = psSGXHostCtl->ui32PowManFlags;
+       if ((ui32PowManFlags & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0) {
+
+       } else {
+
+               if (psSGXDevInfo->ui32CacheControl & SGX_BIF_INVALIDATE_PDCACHE) {
+                       psSGXHostCtl->ui32ResManFlags |=
+                           PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPD;
+                       psSGXDevInfo->ui32CacheControl ^=
+                           SGX_BIF_INVALIDATE_PDCACHE;
+               }
+               if (psSGXDevInfo->ui32CacheControl & SGX_BIF_INVALIDATE_PTCACHE) {
+                       psSGXHostCtl->ui32ResManFlags |=
+                           PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPT;
+                       psSGXDevInfo->ui32CacheControl ^=
+                           SGX_BIF_INVALIDATE_PTCACHE;
+               }
+
+               psSGXHostCtl->sResManCleanupData.uiAddr =
+                   psHWDataDevVAddr->uiAddr;
+
+               psSGXHostCtl->ui32ResManFlags |= ui32ResManRequestFlag;
+
+               PDUMPCOMMENT
+                   ("TA/3D CCB Control - Request clean-up event on uKernel...");
+               PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+                        offsetof(PVRSRV_SGX_HOST_CTL,
+                                 sResManCleanupData.uiAddr),
+                        sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                        hUniqueTag);
+               PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+                        offsetof(PVRSRV_SGX_HOST_CTL, ui32ResManFlags),
+                        sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                        hUniqueTag);
+
+               SGXScheduleProcessQueues(psDeviceNode);
+
+#if !defined(NO_HARDWARE)
+               if (PollForValueKM
+                   ((volatile IMG_UINT32 *)(&psSGXHostCtl->ui32ResManFlags),
+                    PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
+                    PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
+                    MAX_HW_TIME_US / WAIT_TRY_COUNT,
+                    WAIT_TRY_COUNT) != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "SGXCleanupRequest: Wait for uKernel to clean up render context failed"));
+               }
+#endif
+
+#ifdef PDUMP
+
+               PDUMPCOMMENT
+                   ("TA/3D CCB Control - Wait for clean-up request to complete...");
+               PDUMPMEMPOL(psSGXHostCtlMemInfo,
+                           offsetof(PVRSRV_SGX_HOST_CTL, ui32ResManFlags),
+                           PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
+                           PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
+                           PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, IMG_FALSE,
+                           hUniqueTag);
+#endif
+
+               psSGXHostCtl->ui32ResManFlags &= ~(ui32ResManRequestFlag);
+               psSGXHostCtl->ui32ResManFlags &=
+                   ~(PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE);
+               PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+                        offsetof(PVRSRV_SGX_HOST_CTL, ui32ResManFlags),
+                        sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+                        hUniqueTag);
+       }
+}
+
+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_USSE_EDM_RESMAN_CLEANUP_RC_REQUEST);
+
+       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_USSE_EDM_RESMAN_CLEANUP_TC_REQUEST);
+
+       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);
+
+       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;
+
+       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);
+
+       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;
+
+       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_USSE_EDM_RESMAN_CLEANUP_2DC_REQUEST);
+
+       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);
+
+       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);
+
+       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)
+{
+       PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+       return (IMG_BOOL) ((psSyncData->ui32ReadOpsComplete ==
+                           psSyncData->ui32ReadOpsPending)
+                          && (psSyncData->ui32WriteOpsComplete ==
+                              psSyncData->ui32WriteOpsPending)
+           );
+}
+
+IMG_EXPORT
+    PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO * psDevInfo,
+                                          PVRSRV_KERNEL_SYNC_INFO * psSyncInfo,
+                                          IMG_BOOL bWaitForComplete)
+{
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0;
+
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+       PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start"));
+
+       if (SGX2DQuerySyncOpsComplete(psSyncInfo)) {
+
+               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."));
+       do {
+               OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+
+               if (SGX2DQuerySyncOpsComplete(psSyncInfo)) {
+
+                       PVR_DPF((PVR_DBG_CALLTRACE,
+                                "SGX2DQueryBlitsCompleteKM: Wait over.  Blits complete."));
+                       return PVRSRV_OK;
+               }
+
+               if (bStart == IMG_FALSE) {
+                       uiStart = OSClockus();
+                       bStart = IMG_TRUE;
+               }
+
+               OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+       } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+
+       PVR_DPF((PVR_DBG_ERROR,
+                "SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
+
+#if defined(DEBUG)
+       {
+               PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+               PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: %p, Syncdata: %p", psSyncInfo, 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((PVRSRV_DEVICE_NODE *) psDeviceNode,
+                         &sHWRTDataSetDevVAddr,
+                         PVRSRV_USSE_EDM_RESMAN_CLEANUP_RT_REQUEST);
+}
diff --git a/pvr/sgxutils.h b/pvr/sgxutils.h
new file mode 100644 (file)
index 0000000..b66adc3
--- /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 
+ *
+ ******************************************************************************/
+
+#include "perproc.h"
+
+#define GET_CCB_SPACE(WOff, ROff, CCBSize) \
+       (((ROff - WOff) + (CCBSize - 1)) & (CCBSize - 1))
+
+#define UPDATE_CCB_OFFSET(Off, PacketSize, CCBSize) \
+       Off = ((Off + PacketSize) & (CCBSize - 1))
+
+#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 *)(((char *)(psCCBMemInfo)->pvLinAddrKM) + \
+               (psCCBKick)->offset))
+
+static INLINE IMG_UINT32 SGXCalcContextCCBParamSize(IMG_UINT32 ui32ParamSize,
+                                                   IMG_UINT32 ui32AllocGran)
+{
+       return (ui32ParamSize + (ui32AllocGran - 1)) & ~(ui32AllocGran - 1);
+}
+
+static INLINE IMG_PVOID SGXAcquireCCB(PVRSRV_SGX_CCB * psCCB,
+                                     IMG_UINT32 ui32CmdSize)
+{
+       IMG_BOOL bStart = IMG_FALSE;
+       IMG_UINT32 uiStart = 0;
+
+       do {
+               if (GET_CCB_SPACE
+                   (*psCCB->pui32WriteOffset, *psCCB->pui32ReadOffset,
+                    psCCB->ui32Size) > ui32CmdSize) {
+                       return (IMG_PVOID) ((IMG_UINT32) psCCB->psCCBMemInfo->
+                                           pvLinAddrKM +
+                                           *psCCB->pui32WriteOffset);
+               }
+
+               if (bStart == IMG_FALSE) {
+                       bStart = IMG_TRUE;
+                       uiStart = OSClockus();
+               }
+               OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+       } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+
+       return IMG_NULL;
+}
+
+#if defined (PDUMP)
+IMG_VOID DumpBufferArray(PPVR3DIF4_KICKTA_DUMP_BUFFER psBufferArray,
+                        IMG_UINT32 ui32BufferArrayLength, IMG_BOOL bDumpPolls);
+#endif
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+IMG_IMPORT
+    IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode,
+                                    IMG_UINT32 ui32CallerID);
+#endif
+
+IMG_IMPORT
+    PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE * psDeviceNode,
+                                        PVRSRV_SGX_COMMAND_TYPE eCommandType,
+                                        PVRSRV_SGX_COMMAND * psCommandData,
+                                        IMG_UINT32 ui32CallerID);
+
+IMG_IMPORT IMG_VOID SGXScheduleProcessQueues(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
diff --git a/pvr/srvkm.h b/pvr/srvkm.h
new file mode 100644 (file)
index 0000000..9cb58dd
--- /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 SRVKM_H
+#define SRVKM_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+       IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32
+                                                                 ui32PID);
+       IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32
+                                                                ui32PID);
+
+       IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
+
+       PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE
+                                                               hArena,
+                                                               IMG_PBYTE
+                                                               pbyBuffer,
+                                                               IMG_UINT32 *
+                                                               puiBufSize,
+                                                               IMG_BOOL bSave);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/syscommon.h b/pvr/syscommon.h
new file mode 100644 (file)
index 0000000..d12e46e
--- /dev/null
@@ -0,0 +1,192 @@
+/**********************************************************************
+ *
+ * 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"
+
+#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;
+               PVR_POWER_STATE eCurrentPowerState;
+               PVR_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;
+               PFN_CMD_PROC *ppfnCmdProcList[SYS_DEVICE_COUNT];
+
+               PCOMMAND_COMPLETE_DATA *ppsCmdCompleteData[SYS_DEVICE_COUNT];
+
+               IMG_BOOL bReProcessQueues;
+
+               RA_ARENA *apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS];
+
+               IMG_CHAR *pszVersionString;
+               PVRSRV_EVENTOBJECT *psGlobalEventObject;
+       } SYS_DATA;
+
+       PVRSRV_ERROR SysInitialise(IMG_VOID);
+       PVRSRV_ERROR SysFinalise(IMG_VOID);
+
+       IMG_UINT32 GetCPUTranslatedAddress(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(PVR_POWER_STATE eNewPowerState);
+       PVRSRV_ERROR SysSystemPostPowerState(PVR_POWER_STATE eNewPowerState);
+       PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+                                           PVR_POWER_STATE eNewPowerState,
+                                           PVR_POWER_STATE eCurrentPowerState);
+       PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+                                            PVR_POWER_STATE eNewPowerState,
+                                            PVR_POWER_STATE
+                                            eCurrentPowerState);
+
+       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);
+
+       extern SYS_DATA *gpsSysData;
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireData)
+#endif
+       static INLINE PVRSRV_ERROR SysAcquireData(SYS_DATA ** ppsSysData) {
+
+               *ppsSysData = gpsSysData;
+
+               if (!gpsSysData) {
+                       return PVRSRV_ERROR_GENERIC;
+               }
+
+               return PVRSRV_OK;
+       }
+
+#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/pvr/sysconfig.c b/pvr/sysconfig.c
new file mode 100644 (file)
index 0000000..6a6fa74
--- /dev/null
@@ -0,0 +1,737 @@
+/**********************************************************************
+ *
+ * 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 "kerneldisplay.h"
+#include "oemfuncs.h"
+#include "sgxinfo.h"
+#include "pdump_km.h"
+#include "sgxinfokm.h"
+#include "syslocal.h"
+#include "sysconfig.h"
+
+SYS_DATA *gpsSysData = (SYS_DATA *) IMG_NULL;
+SYS_DATA gsSysData;
+
+static SYS_SPECIFIC_DATA gsSysSpecificData;
+
+static IMG_UINT32 gui32SGXDeviceID;
+static SGX_DEVICE_MAP gsSGXDeviceMap;
+static PVRSRV_DEVICE_NODE *gpsSGXDevNode;
+
+#define DEVICE_SGX_INTERRUPT (1 << 0)
+
+#if defined(NO_HARDWARE)
+static IMG_CPU_VIRTADDR gsSGXRegsCPUVAddr;
+#endif
+
+IMG_UINT32 PVRSRV_BridgeDispatchKM(IMG_UINT32 Ioctl,
+                                  IMG_BYTE * pInBuf,
+                                  IMG_UINT32 InBufLen,
+                                  IMG_BYTE * pOutBuf,
+                                  IMG_UINT32 OutBufLen,
+                                  IMG_UINT32 * pdwBytesTransferred);
+
+static PVRSRV_ERROR SysLocateDevices(SYS_DATA * psSysData)
+{
+#if defined(NO_HARDWARE)
+       PVRSRV_ERROR eError;
+       IMG_CPU_PHYADDR sCpuPAddr;
+#endif
+
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+
+       gsSGXDeviceMap.ui32Flags = 0x0;
+
+#if defined(NO_HARDWARE)
+
+       eError = OSBaseAllocContigMemory(SYS_OMAP3430_SGX_REGS_SIZE,
+                                        &gsSGXRegsCPUVAddr, &sCpuPAddr);
+       if (eError != PVRSRV_OK) {
+               return eError;
+       }
+       gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr;
+       gsSGXDeviceMap.sRegsSysPBase =
+           SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase);
+       gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE;
+#if defined(__linux__)
+
+       gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+#else
+
+       gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL;
+#endif
+
+       OSMemSet(gsSGXRegsCPUVAddr, 0, SYS_OMAP3430_SGX_REGS_SIZE);
+
+       gsSGXDeviceMap.ui32IRQ = 0;
+
+#else
+
+       gsSGXDeviceMap.sRegsSysPBase.uiAddr =
+           SYS_OMAP3430_SGX_REGS_SYS_PHYS_BASE;
+       gsSGXDeviceMap.sRegsCpuPBase =
+           SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+       gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE;
+
+       gsSGXDeviceMap.ui32IRQ = SYS_OMAP3430_SGX_IRQ;
+
+#endif
+
+       return PVRSRV_OK;
+}
+
+IMG_CHAR *SysCreateVersionString(IMG_CPU_PHYADDR sRegRegion)
+{
+       static IMG_CHAR aszVersionString[100];
+       SYS_DATA *psSysData;
+       IMG_UINT32 ui32SGXRevision;
+       IMG_INT32 i32Count;
+#if !defined(NO_HARDWARE)
+       IMG_VOID *pvRegsLinAddr;
+
+       pvRegsLinAddr = OSMapPhysToLin(sRegRegion,
+                                      SYS_OMAP3430_SGX_REGS_SIZE,
+                                      PVRSRV_HAP_UNCACHED |
+                                      PVRSRV_HAP_KERNEL_ONLY, IMG_NULL);
+       if (!pvRegsLinAddr) {
+               return IMG_NULL;
+       }
+
+       ui32SGXRevision = OSReadHWReg((IMG_PVOID) ((IMG_PBYTE) pvRegsLinAddr),
+                                     EUR_CR_CORE_REVISION);
+#else
+       ui32SGXRevision = 0;
+#endif
+
+       if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+               return IMG_NULL;
+       }
+
+       i32Count = OSSNPrintf(aszVersionString, 100,
+                             "SGX revision = %u.%u.%u",
+                             (unsigned
+                              int)((ui32SGXRevision &
+                                    EUR_CR_CORE_REVISION_MAJOR_MASK)
+                                   >> EUR_CR_CORE_REVISION_MAJOR_SHIFT),
+                             (unsigned
+                              int)((ui32SGXRevision &
+                                    EUR_CR_CORE_REVISION_MINOR_MASK)
+                                   >> EUR_CR_CORE_REVISION_MINOR_SHIFT),
+                             (unsigned
+                              int)((ui32SGXRevision &
+                                    EUR_CR_CORE_REVISION_MAINTENANCE_MASK)
+                                   >> EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT)
+           );
+
+#if !defined(NO_HARDWARE)
+       OSUnMapPhysToLin(pvRegsLinAddr,
+                        SYS_OMAP3430_SGX_REGS_SIZE,
+                        PVRSRV_HAP_UNCACHED | PVRSRV_HAP_KERNEL_ONLY,
+                        IMG_NULL);
+#endif
+
+       if (i32Count == -1) {
+               return IMG_NULL;
+       }
+
+       return aszVersionString;
+}
+
+PVRSRV_ERROR SysInitialise(IMG_VOID)
+{
+       IMG_UINT32 i;
+       PVRSRV_ERROR eError;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       IMG_CPU_PHYADDR TimerRegPhysBase;
+       SGX_TIMING_INFORMATION *psTimingInfo;
+
+       gpsSysData = &gsSysData;
+       OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
+
+       gpsSysData->pvSysSpecificData = &gsSysSpecificData;
+       gsSysSpecificData.ui32SysSpecificData = 0;
+
+       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;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                             SYS_SPECIFIC_DATA_ENABLE_ENVDATA);
+
+       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;
+       }
+
+       TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE;
+       gpsSysData->pvSOCTimerRegisterKM = IMG_NULL;
+       gpsSysData->hSOCTimerRegisterOSMemHandle = 0;
+       OSReservePhys(TimerRegPhysBase,
+                     4,
+                     PVRSRV_HAP_MULTI_PROCESS | PVRSRV_HAP_UNCACHED,
+                     (IMG_VOID **) & gpsSysData->pvSOCTimerRegisterKM,
+                     &gpsSysData->hSOCTimerRegisterOSMemHandle);
+
+       psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
+       psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+       psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
+       psTimingInfo->ui32ActivePowManLatencyms =
+           SYS_SGX_ACTIVE_POWER_LATENCY_MS;
+       psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
+
+       eError = SysLocateDevices(gpsSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SysInitialise: Failed to locate devices"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                             SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV);
+
+       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;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                             SYS_SPECIFIC_DATA_ENABLE_REGDEV);
+
+       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;
+                               }
+
+                               gpsSGXDevNode = psDeviceNode;
+                               gsSysSpecificData.psSGXDevNode = psDeviceNode;
+
+                               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_ENABLE_PDUMPINIT);
+
+       eError = EnableSystemClocks(gpsSysData, &gsSGXDeviceMap.sTimingInfo);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SysInitialise: Failed to Enable system clocks (%d)",
+                        eError));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                             SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       eError = EnableSGXClocks(gpsSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SysInitialise: Failed to Enable SGX clocks (%d)",
+                        eError));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+#endif
+
+       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_ENABLE_INITDEV);
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+
+       DisableSGXClocks(gpsSysData);
+#endif
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysFinalise(IMG_VOID)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       eError = EnableSGXClocks(gpsSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SysInitialise: Failed to Enable SGX clocks (%d)",
+                        eError));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+#endif
+
+#if defined(SYS_USING_INTERRUPTS)
+
+       eError = OSInstallMISR(gpsSysData);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR, "SysFinalise: Failed to install MISR"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                             SYS_SPECIFIC_DATA_ENABLE_MISR);
+
+       eError =
+           OSInstallDeviceLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ, "SGX ISR",
+                               gpsSGXDevNode);
+       if (eError != PVRSRV_OK) {
+               PVR_DPF((PVR_DBG_ERROR, "SysFinalise: Failed to install ISR"));
+               SysDeinitialise(gpsSysData);
+               gpsSysData = IMG_NULL;
+               return eError;
+       }
+       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                             SYS_SPECIFIC_DATA_ENABLE_LISR);
+#endif
+
+       gpsSysData->pszVersionString =
+           SysCreateVersionString(gsSGXDeviceMap.sRegsCpuPBase);
+       if (!gpsSysData->pszVersionString) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "SysFinalise: Failed to create a system version string"));
+       } else {
+               PVR_DPF((PVR_DBG_WARNING, "SysFinalise: Version string: %s",
+                        gpsSysData->pszVersionString));
+       }
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+
+       DisableSGXClocks(gpsSysData);
+#endif
+
+       return eError;
+}
+
+PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData)
+{
+       PVRSRV_ERROR eError;
+
+       SYS_SPECIFIC_DATA *psSysSpecData =
+           (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+
+#if defined(SYS_USING_INTERRUPTS)
+       if (SYS_SPECIFIC_DATA_TEST
+           (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_LISR)) {
+               eError = OSUninstallDeviceLISR(psSysData);
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "SysDeinitialise: OSUninstallDeviceLISR failed"));
+                       return eError;
+               }
+       }
+
+       if (SYS_SPECIFIC_DATA_TEST
+           (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_MISR)) {
+               eError = OSUninstallMISR(psSysData);
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "SysDeinitialise: OSUninstallMISR failed"));
+                       return eError;
+               }
+       }
+#endif
+
+       if (SYS_SPECIFIC_DATA_TEST
+           (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_INITDEV)) {
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+               PVR_ASSERT(SYS_SPECIFIC_DATA_TEST
+                          (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS));
+
+               eError = EnableSGXClocks(gpsSysData);
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "SysDeinitialise: EnableSGXClocks failed"));
+                       return eError;
+               }
+#endif
+
+               eError = PVRSRVDeinitialiseDevice(gui32SGXDeviceID);
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "SysDeinitialise: failed to de-init the device"));
+                       return eError;
+               }
+       }
+
+       if (SYS_SPECIFIC_DATA_TEST
+           (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)) {
+               DisableSystemClocks(gpsSysData);
+       }
+
+       if (SYS_SPECIFIC_DATA_TEST
+           (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA)) {
+               eError = OSDeInitEnvData(gpsSysData->pvEnvSpecificData);
+               if (eError != PVRSRV_OK) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "SysDeinitialise: failed to de-init env structure"));
+                       return eError;
+               }
+       }
+
+       if (gpsSysData->pvSOCTimerRegisterKM) {
+               OSUnReservePhys(gpsSysData->pvSOCTimerRegisterKM,
+                               4,
+                               PVRSRV_HAP_MULTI_PROCESS | PVRSRV_HAP_UNCACHED,
+                               gpsSysData->hSOCTimerRegisterOSMemHandle);
+       }
+
+       SysDeinitialiseCommon(gpsSysData);
+
+#if defined(NO_HARDWARE)
+       if (SYS_SPECIFIC_DATA_TEST
+           (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV)) {
+
+               OSBaseFreeContigMemory(SYS_OMAP3430_SGX_REGS_SIZE,
+                                      gsSGXRegsCPUVAddr,
+                                      gsSGXDeviceMap.sRegsCpuPBase);
+       }
+#endif
+
+       if (SYS_SPECIFIC_DATA_TEST
+           (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT)) {
+               PDUMPDEINIT();
+       }
+
+       psSysSpecData->ui32SysSpecificData = 0;
+       gpsSysData = IMG_NULL;
+
+       return PVRSRV_OK;
+}
+
+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)
+{
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA * psSysData,
+                                PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+#if defined(NO_HARDWARE)
+
+       return 0xFFFFFFFF;
+#else
+
+       return psDeviceNode->ui32SOCInterruptBit;
+#endif
+}
+
+IMG_VOID SysClearInterrupts(SYS_DATA * psSysData, IMG_UINT32 ui32ClearBits)
+{
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+       PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+
+}
+
+PVRSRV_ERROR SysSystemPrePowerState(PVR_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (eNewPowerState == PVRSRV_POWER_STATE_D3) {
+               PVR_TRACE(("SysSystemPrePowerState: Entering state D3"));
+
+#if defined(SYS_USING_INTERRUPTS)
+               if (SYS_SPECIFIC_DATA_TEST
+                   (&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR)) {
+                       eError = OSUninstallDeviceLISR(gpsSysData);
+                       if (eError != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SysSystemPrePowerState: OSUninstallDeviceLISR failed (%d)",
+                                        eError));
+                               return eError;
+                       }
+                       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                                             SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+                       SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData,
+                                               SYS_SPECIFIC_DATA_ENABLE_LISR);
+               }
+#endif
+
+               if (SYS_SPECIFIC_DATA_TEST
+                   (&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)) {
+                       DisableSystemClocks(gpsSysData);
+
+                       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                                             SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS);
+                       SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData,
+                                               SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+               }
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR SysSystemPostPowerState(PVR_POWER_STATE eNewPowerState)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (eNewPowerState == PVRSRV_POWER_STATE_D0) {
+               PVR_TRACE(("SysSystemPostPowerState: Entering state D0"));
+
+               if (SYS_SPECIFIC_DATA_TEST
+                   (&gsSysSpecificData,
+                    SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS)) {
+                       eError =
+                           EnableSystemClocks(gpsSysData,
+                                              &gsSGXDeviceMap.sTimingInfo);
+                       if (eError != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SysSystemPostPowerState: EnableSystemClocks failed (%d)",
+                                        eError));
+                               return eError;
+                       }
+                       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                                             SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+                       SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData,
+                                               SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS);
+               }
+#if defined(SYS_USING_INTERRUPTS)
+               if (SYS_SPECIFIC_DATA_TEST
+                   (&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR)) {
+                       eError =
+                           OSInstallDeviceLISR(gpsSysData,
+                                               gsSGXDeviceMap.ui32IRQ,
+                                               "SGX ISR", gpsSGXDevNode);
+                       if (eError != PVRSRV_OK) {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "SysSystemPostPowerState: OSInstallDeviceLISR failed to install ISR (%d)",
+                                        eError));
+                               return eError;
+                       }
+                       SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+                                             SYS_SPECIFIC_DATA_ENABLE_LISR);
+                       SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData,
+                                               SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+               }
+#endif
+       }
+       return eError;
+}
+
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+                                   PVR_POWER_STATE eNewPowerState,
+                                   PVR_POWER_STATE eCurrentPowerState)
+{
+       PVR_UNREFERENCED_PARAMETER(eCurrentPowerState);
+
+       if (ui32DeviceIndex != gui32SGXDeviceID) {
+               return PVRSRV_OK;
+       }
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       if (eNewPowerState == PVRSRV_POWER_STATE_D3) {
+               PVR_TRACE(("SysDevicePrePowerState: SGX Entering state D3"));
+               DisableSGXClocks(gpsSysData);
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(eNewPowerState);
+#endif
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+                                    PVR_POWER_STATE eNewPowerState,
+                                    PVR_POWER_STATE eCurrentPowerState)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       PVR_UNREFERENCED_PARAMETER(eNewPowerState);
+
+       if (ui32DeviceIndex != gui32SGXDeviceID) {
+               return eError;
+       }
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       if (eCurrentPowerState == PVRSRV_POWER_STATE_D3) {
+               PVR_TRACE(("SysDevicePostPowerState: SGX Leaving state D3"));
+               eError = EnableSGXClocks(gpsSysData);
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(eCurrentPowerState);
+#endif
+
+       return eError;
+}
+
+PVRSRV_ERROR SysOEMFunction(IMG_UINT32 ui32ID,
+                           IMG_VOID * pvIn,
+                           IMG_UINT32 ulInSize,
+                           IMG_VOID * pvOut, IMG_UINT32 ulOutSize)
+{
+       PVR_UNREFERENCED_PARAMETER(ui32ID);
+       PVR_UNREFERENCED_PARAMETER(pvIn);
+       PVR_UNREFERENCED_PARAMETER(ulInSize);
+       PVR_UNREFERENCED_PARAMETER(pvOut);
+       PVR_UNREFERENCED_PARAMETER(ulOutSize);
+
+       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;
+               return PVRSRV_OK;
+       }
+
+       return PVRSRV_ERROR_INVALID_PARAMS;
+}
diff --git a/pvr/sysconfig.h b/pvr/sysconfig.h
new file mode 100644 (file)
index 0000000..81ce9ad
--- /dev/null
@@ -0,0 +1,51 @@
+/**********************************************************************
+ *
+ * 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"
+
+#define VS_PRODUCT_NAME        "OMAP3430"
+
+#define SYS_SGX_CLOCK_SPEED    110666666
+#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ                (100)
+#define SYS_SGX_PDS_TIMER_FREQ                 (1000)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS                (500)
+
+#define        SYS_OMAP3430_VDD2_OPP3_SGX_CLOCK_SPEED SYS_SGX_CLOCK_SPEED
+#define SYS_OMAP3430_VDD2_OPP2_SGX_CLOCK_SPEED (SYS_SGX_CLOCK_SPEED / 2)
+
+#define SYS_OMAP3430_SGX_REGS_SYS_PHYS_BASE  0x50000000
+#define SYS_OMAP3430_SGX_REGS_SIZE           0x4000
+
+#define SYS_OMAP3430_SGX_IRQ                            21
+
+#define SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE  0x48088024
+#define SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE       0x48088028
+#define SYS_OMAP3430_GP11TIMER_TSICR_SYS_PHYS_BASE      0x48088040
+
+#endif
diff --git a/pvr/sysinfo.h b/pvr/sysinfo.h
new file mode 100644 (file)
index 0000000..4d39be3
--- /dev/null
@@ -0,0 +1,95 @@
+/**********************************************************************
+ *
+ * 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 3
+
+#define PRM_REG32(offset)        (offset)
+#define CM_REG32(offset)         (offset)
+
+#define CM_FCLKEN_SGX          CM_REG32(0xB00)
+#define                CM_FCLKEN_SGX_EN_3D                                     0x00000002
+
+#define CM_ICLKEN_SGX          CM_REG32(0xB10)
+#define                CM_ICLKEN_SGX_EN_SGX                            0x00000001
+
+#define CM_IDLEST_SGX          CM_REG32(0xB20)
+#define                CM_IDLEST_SGX_ST_SGX                            0x00000001
+
+#define CM_CLKSEL_SGX          CM_REG32(0xB40)
+#define                CM_CLKSEL_SGX_MASK                                      0x0000000f
+#define                CM_CLKSEL_SGX_L3DIV3                            0x00000000
+#define                CM_CLKSEL_SGX_L3DIV4                            0x00000001
+#define                CM_CLKSEL_SGX_L3DIV6                            0x00000002
+#define                CM_CLKSEL_SGX_96M                                       0x00000003
+
+#define CM_SLEEPDEP_SGX                CM_REG32(0xB44)
+#define CM_CLKSTCTRL_SGX       CM_REG32(0xB48)
+#define        CM_CLKSTCTRL_SGX_AUTOSTATE                      0x00008001
+
+#define CM_CLKSTST_SGX         CM_REG32(0xB4C)
+#define        CM_CLKSTST_SGX_STATUS_VALID                     0x00000001
+
+#define RM_RSTST_SGX           PRM_REG32(0xB58)
+#define        RM_RSTST_SGX_RST_MASK                           0x0000000F
+#define        RM_RSTST_SGX_COREDOMAINWKUP_RST         0x00000008
+#define        RM_RSTST_SGX_DOMAINWKUP_RST                     0x00000004
+#define        RM_RSTST_SGX_GLOBALWARM_RST                     0x00000002
+#define        RM_RSTST_SGX_GLOBALCOLD_RST                     0x00000001
+
+#define PM_WKDEP_SGX           PRM_REG32(0xBC8)
+#define        PM_WKDEP_SGX_EN_WAKEUP                          0x00000010
+#define        PM_WKDEP_SGX_EN_MPU                                     0x00000002
+#define        PM_WKDEP_SGX_EN_CORE                            0x00000001
+
+#define PM_PWSTCTRL_SGX                PRM_REG32(0xBE0)
+#define                PM_PWSTCTRL_SGX_POWERSTATE_MASK         0x00000003
+#define                        PM_PWSTCTRL_SGX_OFF                             0x00000000
+#define                        PM_PWSTCTRL_SGX_RETENTION               0x00000001
+#define                        PM_PWSTCTRL_SGX_ON                              0x00000003
+
+#define PM_PWSTST_SGX          PRM_REG32(0xBE4)
+#define                PM_PWSTST_SGX_INTRANSITION                      0x00100000
+#define                PM_PWSTST_SGX_CLKACTIVITY                       0x00080000
+#define                PM_PWSTST_SGX_POWERSTATE_MASK           0x00000003
+#define                        PM_PWSTST_SGX_OFF                               0x00000003
+#define                        PM_PWSTST_SGX_RETENTION                 0x00000001
+#define                        PM_PWSTST_SGX_ON                                0x00000000
+
+#define PM_PREPWSTST_SGX       PRM_REG32(0xBE8)
+
+#endif
diff --git a/pvr/syslocal.h b/pvr/syslocal.h
new file mode 100644 (file)
index 0000000..c541e7a
--- /dev/null
@@ -0,0 +1,106 @@
+/**********************************************************************
+ *
+ * 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__
+
+#if defined(__linux__)
+#include <linux/version.h>
+#include <linux/clk.h>
+#if defined (SUPPORT_TI_PM)
+#include <asm/semaphore.h>
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+#include <asm/arch/resource.h>
+#endif
+#else
+#include <linux/semaphore.h>
+#endif
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+       IMG_CHAR *SysCreateVersionString(IMG_CPU_PHYADDR sRegRegion);
+
+       IMG_VOID DisableSystemClocks(SYS_DATA * psSysData);
+       PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData,
+                                       SGX_TIMING_INFORMATION *
+                                       psSGXTimingInfo);
+
+       IMG_VOID DisableSGXClocks(SYS_DATA * psSysData);
+       PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData);
+
+#define SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS     0x00000001
+#define SYS_SPECIFIC_DATA_ENABLE_LISR          0x00000002
+#define SYS_SPECIFIC_DATA_ENABLE_MISR          0x00000004
+#define SYS_SPECIFIC_DATA_ENABLE_ENVDATA       0x00000008
+#define SYS_SPECIFIC_DATA_ENABLE_LOCDEV                0x00000010
+#define SYS_SPECIFIC_DATA_ENABLE_REGDEV                0x00000020
+#define SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT     0x00000040
+#define SYS_SPECIFIC_DATA_ENABLE_INITDEV       0x00000080
+#define SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV     0x00000100
+
+#define        SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR     0x00000200
+#define        SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS  0x00000400
+
+#define        SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) ((void)((psSysSpecData)->ui32SysSpecificData |= (flag)))
+
+#define        SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, flag) ((void)((psSysSpecData)->ui32SysSpecificData &= ~(flag)))
+
+#define        SYS_SPECIFIC_DATA_TEST(psSysSpecData, flag) (((psSysSpecData)->ui32SysSpecificData & (flag)) != 0)
+
+       typedef struct _SYS_SPECIFIC_DATA_TAG_ {
+               IMG_UINT32 ui32SysSpecificData;
+               IMG_BOOL bSGXClocksEnabled;
+               PVRSRV_DEVICE_NODE *psSGXDevNode;
+#if defined(__linux__)
+               IMG_BOOL bSysClocksOneTimeInit;
+
+               struct clk *psCORE_CK;
+               struct clk *psSGX_FCK;
+               struct clk *psSGX_ICK;
+               struct clk *psMPU_CK;
+#if defined(DEBUG) || defined(TIMING)
+               struct clk *psGPT11_FCK;
+               struct clk *psGPT11_ICK;
+#endif
+#if defined (SUPPORT_TI_PM)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+               SGX_TIMING_INFORMATION *psSGXTimingInfo;
+
+               struct constraint_handle *pVdd2Handle;
+#endif
+#endif
+
+               struct semaphore sConstraintNotifierLock;
+#endif
+       } SYS_SPECIFIC_DATA;
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/pvr/sysutils.c b/pvr/sysutils.c
new file mode 100644 (file)
index 0000000..02c9831
--- /dev/null
@@ -0,0 +1,29 @@
+/**********************************************************************
+ *
+ * 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 "sysutils_linux.c"
+#endif
diff --git a/pvr/sysutils_linux.c b/pvr/sysutils_linux.c
new file mode 100644 (file)
index 0000000..1d1e848
--- /dev/null
@@ -0,0 +1,578 @@
+/**********************************************************************
+ *
+ * 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/clk.h>
+#include <linux/err.h>
+#include <linux/hardirq.h>
+#include <asm/bug.h>
+#if defined (SUPPORT_TI_PM)
+#include <asm/semaphore.h>
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+#include <asm/arch/resource.h>
+#endif
+#endif
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sysinfo.h"
+#include "sgxapi_km.h"
+#include "sysconfig.h"
+#include "sgxinfokm.h"
+#include "syslocal.h"
+
+#define        HZ_TO_MHZ(m) ((m) / 1000000)
+
+#define        MUTEX_INIT(pl)          init_MUTEX(pl)
+#define        MUTEX_LOCK(pl)          down(pl)
+#define        MUTEX_UNLOCK(pl)        up(pl)
+#if defined (SUPPORT_TI_PM)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+
+static SYS_SPECIFIC_DATA *psNotifierSysSpecData;
+
+static inline unsigned long scale_by_rate(unsigned long val,
+                                         unsigned long rate1,
+                                         unsigned long rate2)
+{
+       if (rate1 >= rate2) {
+               return val * (rate1 / rate2);
+       }
+
+       return val / (rate2 / rate1);
+}
+
+static inline unsigned long scale_prop_to_SGX_clock(unsigned long val,
+                                                   unsigned long rate)
+{
+       return scale_by_rate(val, rate, SYS_SGX_CLOCK_SPEED);
+}
+
+static inline unsigned long scale_inv_prop_to_SGX_clock(unsigned long val,
+                                                       unsigned long rate)
+{
+       return scale_by_rate(val, SYS_SGX_CLOCK_SPEED, rate);
+}
+
+static void post_clock_rate_change(void)
+{
+       unsigned long rate;
+       SGX_TIMING_INFORMATION *psTimingInfo =
+           psNotifierSysSpecData->psSGXTimingInfo;
+
+       rate = clk_get_rate(psNotifierSysSpecData->psSGX_FCK);
+
+       PVR_ASSERT(rate != 0);
+
+       psTimingInfo->ui32CoreClockSpeed = rate;
+       psTimingInfo->ui32HWRecoveryFreq =
+           scale_prop_to_SGX_clock(SYS_SGX_HWRECOVERY_TIMEOUT_FREQ, rate);
+       psTimingInfo->ui32uKernelFreq =
+           scale_prop_to_SGX_clock(SYS_SGX_PDS_TIMER_FREQ, rate);
+
+       PVR_TRACE(("post_clock_rate_change: SGX clock rate: %dMHz",
+                  HZ_TO_MHZ(psTimingInfo->ui32CoreClockSpeed)));
+
+#if 0
+       PVR_TRACE(("post_clock_rate_change: HW Recovery frequency: %dHz",
+                  psTimingInfo->ui32HWRecoveryFreq));
+       PVR_TRACE(("post_clock_rate_change: PDS Timer frequency: %dHz",
+                  psTimingInfo->ui32uKernelFreq));
+#endif
+
+       PVRSRVDevicePostClockSpeedChange(psNotifierSysSpecData->psSGXDevNode->
+                                        sDevId.ui32DeviceIndex, IMG_FALSE,
+                                        IMG_NULL);
+}
+
+static void pre_clock_rate_change(void)
+{
+       PVRSRVDevicePreClockSpeedChange(psNotifierSysSpecData->psSGXDevNode->
+                                       sDevId.ui32DeviceIndex, IMG_FALSE,
+                                       IMG_NULL);
+
+}
+
+static int vdd2_post_func(struct notifier_block *n, unsigned long event,
+                         void *ptr)
+{
+       PVR_UNREFERENCED_PARAMETER(n);
+       PVR_UNREFERENCED_PARAMETER(event);
+       PVR_UNREFERENCED_PARAMETER(ptr);
+
+       BUG_ON(in_irq());
+
+       if (psNotifierSysSpecData->bSGXClocksEnabled) {
+               post_clock_rate_change();
+       }
+
+       MUTEX_UNLOCK(&psNotifierSysSpecData->sConstraintNotifierLock);
+
+       return 0;
+}
+
+static int vdd2_pre_func(struct notifier_block *n, unsigned long event,
+                        void *ptr)
+{
+       PVR_UNREFERENCED_PARAMETER(n);
+       PVR_UNREFERENCED_PARAMETER(event);
+       PVR_UNREFERENCED_PARAMETER(ptr);
+
+       BUG_ON(in_irq());
+
+       MUTEX_LOCK(&psNotifierSysSpecData->sConstraintNotifierLock);
+
+       if (psNotifierSysSpecData->bSGXClocksEnabled) {
+               pre_clock_rate_change();
+       }
+
+       return 0;
+}
+
+static struct notifier_block vdd2_pre = {
+       vdd2_pre_func,
+       NULL
+};
+
+static struct notifier_block vdd2_post = {
+       vdd2_post_func,
+       NULL
+};
+
+static struct constraint_id cnstr_id_vdd2 = {
+       .type = RES_OPP_CO,
+       .data = (void *)"vdd2_opp"
+};
+
+static IMG_VOID RegisterConstraintNotifications(SYS_DATA * psSysData,
+                                               SGX_TIMING_INFORMATION *
+                                               psSGXTimingInfo)
+{
+       PVR_TRACE(("Registering constraint notifications"));
+
+       PVR_ASSERT(psNotifierSysSpecData == IMG_NULL);
+
+       psNotifierSysSpecData =
+           (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+       psNotifierSysSpecData->psSGXTimingInfo = psSGXTimingInfo;
+
+       constraint_register_pre_notification(psNotifierSysSpecData->pVdd2Handle,
+                                            &vdd2_pre, max_vdd2_opp + 1);
+
+       constraint_register_post_notification(psNotifierSysSpecData->
+                                             pVdd2Handle, &vdd2_post,
+                                             max_vdd2_opp + 1);
+
+       PVR_TRACE(("VDD2 constraint notifications registered"));
+}
+
+static IMG_VOID UnRegisterConstraintNotifications(IMG_VOID)
+{
+       if (psNotifierSysSpecData == IMG_NULL) {
+               return;
+       }
+
+       PVR_TRACE(("Unregistering constraint notifications"));
+
+       constraint_unregister_pre_notification(psNotifierSysSpecData->
+                                              pVdd2Handle, &vdd2_pre,
+                                              max_vdd2_opp + 1);
+
+       constraint_unregister_post_notification(psNotifierSysSpecData->
+                                               pVdd2Handle, &vdd2_post,
+                                               max_vdd2_opp + 1);
+
+       psNotifierSysSpecData = IMG_NULL;
+}
+#endif
+#endif
+PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData)
+{
+#if !defined(NO_HARDWARE)
+       SYS_SPECIFIC_DATA *psSysSpecData =
+           (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+       unsigned long rate;
+       int res;
+
+       if (psSysSpecData->bSGXClocksEnabled) {
+               return PVRSRV_OK;
+       }
+
+       PVR_TRACE(("EnableSGXClocks: Enabling SGX Clocks"));
+
+#if defined(DEBUG)
+       rate = clk_get_rate(psSysSpecData->psMPU_CK);
+       PVR_TRACE(("CPU Clock is %dMhz", HZ_TO_MHZ(rate)));
+#endif
+
+       res = clk_enable(psSysSpecData->psSGX_FCK);
+       if (res < 0) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSGXClocks: Couldn't enable SGX functional clock (%d)",
+                        res));
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       res = clk_enable(psSysSpecData->psSGX_ICK);
+       if (res < 0) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSGXClocks: Couldn't enable SGX interface clock (%d)",
+                        res));
+
+               clk_disable(psSysSpecData->psSGX_FCK);
+               return PVRSRV_ERROR_GENERIC;
+       }
+
+       rate = clk_get_rate(psSysSpecData->psSGX_FCK);
+       if (rate < SYS_SGX_CLOCK_SPEED) {
+               PVR_TRACE(("SGX Functional Clock rate is %dMhz. Attempting to set to %dMhz", HZ_TO_MHZ(rate), HZ_TO_MHZ(SYS_SGX_CLOCK_SPEED)));
+               res =
+                   clk_set_rate(psSysSpecData->psSGX_FCK, SYS_SGX_CLOCK_SPEED);
+               if (res < 0) {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                "EnableSGXClocks: Couldn't set SGX Functional Clock rate (%d)",
+                                res));
+               }
+       }
+       PVR_TRACE(("SGX Functional Clock rate is %dMhz",
+                  HZ_TO_MHZ(clk_get_rate(psSysSpecData->psSGX_FCK))));
+
+#if defined (SUPPORT_TI_PM)
+       BUG_ON(in_irq());
+#endif
+       MUTEX_LOCK(&psSysSpecData->sConstraintNotifierLock);
+
+       psSysSpecData->bSGXClocksEnabled = IMG_TRUE;
+#if defined (SUPPORT_TI_PM)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+
+       pre_clock_rate_change();
+
+       post_clock_rate_change();
+#endif
+#endif
+
+       MUTEX_UNLOCK(&psSysSpecData->sConstraintNotifierLock);
+
+#else
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+#endif
+       return PVRSRV_OK;
+}
+
+IMG_VOID DisableSGXClocks(SYS_DATA * psSysData)
+{
+#if !defined(NO_HARDWARE)
+       SYS_SPECIFIC_DATA *psSysSpecData =
+           (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+       if (!psSysSpecData->bSGXClocksEnabled) {
+               return;
+       }
+
+       PVR_TRACE(("DisableSGXClocks: Disabling SGX Clocks"));
+
+       if (psSysSpecData->psSGX_ICK) {
+               clk_disable(psSysSpecData->psSGX_ICK);
+       }
+
+       if (psSysSpecData->psSGX_FCK) {
+               clk_disable(psSysSpecData->psSGX_FCK);
+       }
+       MUTEX_LOCK(&psSysSpecData->sConstraintNotifierLock);
+
+       psSysSpecData->bSGXClocksEnabled = IMG_FALSE;
+
+       MUTEX_UNLOCK(&psSysSpecData->sConstraintNotifierLock);
+#else
+       PVR_UNREFERENCED_PARAMETER(psSysData);
+#endif
+}
+
+PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData,
+                               SGX_TIMING_INFORMATION * psSGXTimingInfo)
+{
+       SYS_SPECIFIC_DATA *psSysSpecData =
+           (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+       struct clk *psCLK;
+       int res;
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       PVRSRV_ERROR eError;
+#endif
+#if defined(DEBUG) || defined(TIMING)
+       int rate;
+       struct clk *sys_ck;
+       IMG_CPU_PHYADDR TimerRegPhysBase;
+       IMG_HANDLE hTimerEnable;
+       IMG_UINT32 *pui32TimerEnable;
+
+#endif
+
+       PVR_TRACE(("EnableSystemClocks: Enabling System Clocks"));
+
+       if (!psSysSpecData->bSysClocksOneTimeInit) {
+               MUTEX_INIT(&psSysSpecData->sConstraintNotifierLock);
+               psCLK = clk_get(NULL, "core_ck");
+               if (IS_ERR(psCLK)) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "EnableSsystemClocks: Couldn't get Core Clock"));
+                       goto ExitError;
+               }
+               psSysSpecData->psCORE_CK = psCLK;
+
+               psCLK = clk_get(NULL, "sgx_fck");
+               if (IS_ERR(psCLK)) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "EnableSsystemClocks: Couldn't get SGX Functional Clock"));
+                       goto ExitError;
+               }
+               psSysSpecData->psSGX_FCK = psCLK;
+
+               psCLK = clk_get(NULL, "sgx_ick");
+               if (IS_ERR(psCLK)) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "EnableSystemClocks: Couldn't get SGX Interface Clock"));
+                       goto ExitError;
+               }
+               psSysSpecData->psSGX_ICK = psCLK;
+
+#if defined(DEBUG)
+               psCLK = clk_get(NULL, "mpu_ck");
+               if (IS_ERR(psCLK)) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "EnableSystemClocks: Couldn't get MPU Clock"));
+                       goto ExitError;
+               }
+               psSysSpecData->psMPU_CK = psCLK;
+#endif
+               res =
+                   clk_set_parent(psSysSpecData->psSGX_FCK,
+                                  psSysSpecData->psCORE_CK);
+               if (res < 0) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "EnableSystemClocks: Couldn't set SGX parent clock (%d)",
+                                res));
+                       goto ExitError;
+               }
+
+               psSysSpecData->bSysClocksOneTimeInit = IMG_TRUE;
+       }
+#if defined (SUPPORT_TI_PM)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+       psSysSpecData->pVdd2Handle = constraint_get("pvrsrvkm", &cnstr_id_vdd2);
+       if (IS_ERR(psSysSpecData->pVdd2Handle)) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSystemClocks: Couldn't get VDD2 constraint handle"));
+               goto ExitError;
+       }
+
+       RegisterConstraintNotifications(psSysData, psSGXTimingInfo);
+#endif
+#endif
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+
+       eError = EnableSGXClocks(psSysData);
+       if (eError != PVRSRV_OK) {
+               goto ExitUnRegisterConstraintNotifications;
+       }
+#endif
+
+#if defined(DEBUG) || defined(TIMING)
+
+       psCLK = clk_get(NULL, "gpt11_fck");
+       if (IS_ERR(psCLK)) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSystemClocks: Couldn't get GPTIMER11 functional clock"));
+               goto ExitDisableSGXClocks;
+       }
+       psSysSpecData->psGPT11_FCK = psCLK;
+
+       psCLK = clk_get(NULL, "gpt11_ick");
+       if (IS_ERR(psCLK)) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSystemClocks: Couldn't get GPTIMER11 interface clock"));
+               goto ExitDisableSGXClocks;
+       }
+       psSysSpecData->psGPT11_ICK = psCLK;
+
+       sys_ck = clk_get(NULL, "sys_ck");
+       if (IS_ERR(sys_ck)) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSystemClocks: Couldn't get System clock"));
+               goto ExitDisableSGXClocks;
+       }
+
+       if (clk_get_parent(psSysSpecData->psGPT11_FCK) != sys_ck) {
+               PVR_TRACE(("Setting GPTIMER11 parent to System Clock"));
+               res = clk_set_parent(psSysSpecData->psGPT11_FCK, sys_ck);
+               if (res < 0) {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "EnableSystemClocks: Couldn't set GPTIMER11 parent clock (%d)",
+                                res));
+                       goto ExitDisableSGXClocks;
+               }
+       }
+
+       rate = clk_get_rate(psSysSpecData->psGPT11_FCK);
+       PVR_TRACE(("GPTIMER11 clock is %dMHz", HZ_TO_MHZ(rate)));
+
+       res = clk_enable(psSysSpecData->psGPT11_FCK);
+       if (res < 0) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSystemClocks: Couldn't enable GPTIMER11 functional clock (%d)",
+                        res));
+               goto ExitDisableSGXClocks;
+       }
+
+       res = clk_enable(psSysSpecData->psGPT11_ICK);
+       if (res < 0) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSystemClocks: Couldn't enable GPTIMER11 interface clock (%d)",
+                        res));
+               goto ExitDisableGPT11FCK;
+       }
+
+       TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_TSICR_SYS_PHYS_BASE;
+       pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase,
+                                         4,
+                                         PVRSRV_HAP_KERNEL_ONLY |
+                                         PVRSRV_HAP_UNCACHED, &hTimerEnable);
+
+       if (pui32TimerEnable == IMG_NULL) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSystemClocks: OSMapPhysToLin failed"));
+               goto ExitDisableGPT11ICK;
+       }
+
+       rate = *pui32TimerEnable;
+       if (!(rate & 4)) {
+               PVR_TRACE(("Setting GPTIMER11 mode to posted (currently is non-posted)"));
+
+               *pui32TimerEnable = rate | 4;
+       }
+
+       OSUnMapPhysToLin(pui32TimerEnable,
+                        4,
+                        PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
+                        hTimerEnable);
+
+       TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE;
+       pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase,
+                                         4,
+                                         PVRSRV_HAP_KERNEL_ONLY |
+                                         PVRSRV_HAP_UNCACHED, &hTimerEnable);
+
+       if (pui32TimerEnable == IMG_NULL) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "EnableSystemClocks: OSMapPhysToLin failed"));
+               goto ExitDisableGPT11ICK;
+       }
+
+       *pui32TimerEnable = 3;
+
+       OSUnMapPhysToLin(pui32TimerEnable,
+                        4,
+                        PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
+                        hTimerEnable);
+
+#endif
+
+       return PVRSRV_OK;
+
+#if defined(DEBUG) || defined(TIMING)
+ExitDisableGPT11ICK:
+       clk_disable(psSysSpecData->psGPT11_ICK);
+ExitDisableGPT11FCK:
+       clk_disable(psSysSpecData->psGPT11_FCK);
+ExitDisableSGXClocks:
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+       DisableSGXClocks(psSysData);
+#endif
+#endif
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ExitUnRegisterConstraintNotifications:
+#endif
+#if defined (SUPPORT_TI_PM)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+       UnRegisterConstraintNotifications();
+       constraint_put(psSysSpecData->pVdd2Handle);
+#endif
+#endif
+ExitError:
+       return PVRSRV_ERROR_GENERIC;
+}
+
+IMG_VOID DisableSystemClocks(SYS_DATA * psSysData)
+{
+#if defined(SUPPORT_TI_PM) || defined(DEBUG) || defined(TIMING)
+       SYS_SPECIFIC_DATA *psSysSpecData =
+           (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+#endif
+#if defined(DEBUG) || defined(TIMING)
+       IMG_CPU_PHYADDR TimerRegPhysBase;
+       IMG_HANDLE hTimerDisable;
+       IMG_UINT32 *pui32TimerDisable;
+#endif
+
+       PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
+#if defined (SUPPORT_TI_PM)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+       UnRegisterConstraintNotifications();
+#endif
+#endif
+
+       DisableSGXClocks(psSysData);
+
+#if defined(DEBUG) || defined(TIMING)
+
+       TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE;
+       pui32TimerDisable = OSMapPhysToLin(TimerRegPhysBase,
+                                          4,
+                                          PVRSRV_HAP_KERNEL_ONLY |
+                                          PVRSRV_HAP_UNCACHED, &hTimerDisable);
+
+       if (pui32TimerDisable == IMG_NULL) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DisableSystemClocks: OSMapPhysToLin failed"));
+       } else {
+               *pui32TimerDisable = 0;
+
+               OSUnMapPhysToLin(pui32TimerDisable,
+                                4,
+                                PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
+                                hTimerDisable);
+       }
+
+       clk_disable(psSysSpecData->psGPT11_ICK);
+
+       clk_disable(psSysSpecData->psGPT11_FCK);
+
+#endif
+#if defined (SUPPORT_TI_PM)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+       constraint_put(psSysSpecData->pVdd2Handle);
+#endif
+#endif
+}
diff --git a/pvr/tools/dbgdriv.c b/pvr/tools/dbgdriv.c
new file mode 100644 (file)
index 0000000..4004609
--- /dev/null
@@ -0,0 +1,1703 @@
+/**********************************************************************
+ *
+ * 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"
+
+#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;
+} DBG_LASTFRAME_BUFFER, *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,
+       ExtDBGDrivEndInitPhase,
+       ExtDBGDrivIsCaptureFrame,
+       ExtDBGDrivWriteLF,
+       ExtDBGDrivReadLF,
+       ExtDBGDrivGetStreamOffset,
+       ExtDBGDrivSetStreamOffset,
+       ExtDBGDrivIsLastCaptureFrame,
+};
+
+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);
+
+       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_UINT32 IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+       IMG_UINT32 ui32Ret;
+
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret = DBGDrivIsLastCaptureFrame(psStream);
+
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream,
+                                                IMG_BOOL bCheckPreviousFrame)
+{
+       IMG_UINT32 ui32Ret;
+
+       HostAquireMutex(g_pvAPIMutex);
+
+       ui32Ret = DBGDrivIsCaptureFrame(psStream, bCheckPreviousFrame);
+
+       HostReleaseMutex(g_pvAPIMutex);
+
+       return ui32Ret;
+}
+
+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 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 ExtDBGDrivEndInitPhase(PDBG_STREAM psStream)
+{
+
+       HostAquireMutex(g_pvAPIMutex);
+
+       DBGDrivEndInitPhase(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_UINT32 AtoI(char *szIn)
+{
+       IMG_UINT32 ui32Len = 0;
+       IMG_UINT32 ui32Value = 0;
+       IMG_UINT32 ui32Digit = 1;
+       IMG_UINT32 ui32Base = 10;
+       int iPos;
+       char bc;
+
+       while (szIn[ui32Len] > 0) {
+               ui32Len++;
+       }
+
+       if (ui32Len == 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 = ui32Len - 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 += bc * ui32Digit;
+
+               ui32Digit = ui32Digit * ui32Base;
+       }
+       return (ui32Value);
+}
+
+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);
+}
+
+void Write(PDBG_STREAM psStream, IMG_UINT8 * pui8Data,
+          IMG_UINT32 ui32InBuffSize)
+{
+
+       if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size) {
+               IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
+               IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
+
+               HostMemCopy((IMG_VOID *) (psStream->ui32Base +
+                                         psStream->ui32WPtr),
+                           (IMG_VOID *) pui8Data, ui32B1);
+
+               HostMemCopy((IMG_VOID *) psStream->ui32Base,
+                           (IMG_VOID *) ((IMG_UINT32) pui8Data + ui32B1),
+                           ui32B2);
+
+               psStream->ui32WPtr = ui32B2;
+       } else {
+               HostMemCopy((IMG_VOID *) (psStream->ui32Base +
+                                         psStream->ui32WPtr),
+                           (IMG_VOID *) pui8Data, ui32InBuffSize);
+
+               psStream->ui32WPtr += ui32InBuffSize;
+
+               if (psStream->ui32WPtr == psStream->ui32Size) {
+                       psStream->ui32WPtr = 0;
+               }
+       }
+       psStream->ui32DataWritten += ui32InBuffSize;
+}
+
+void MonoOut(IMG_CHAR * pszString, IMG_BOOL bNewLine)
+{
+       IMG_UINT32 i;
+       IMG_CHAR *pScreen;
+
+       pScreen = (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);
+       }
+}
+
+void AppendName(IMG_CHAR * pszOut, IMG_CHAR * pszBase, IMG_CHAR * pszName)
+{
+       IMG_UINT32 i;
+       IMG_UINT32 ui32Off;
+
+       i = 0;
+
+       while (pszBase[i] != 0) {
+               pszOut[i] = pszBase[i];
+               i++;
+       }
+
+       ui32Off = i;
+       i = 0;
+
+       while (pszName[i] != 0) {
+               pszOut[ui32Off + i] = pszName[i];
+               i++;
+       }
+
+       pszOut[ui32Off + i] = pszName[i];
+}
+
+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;
+       IMG_UINT32 ui32Off;
+       IMG_VOID *pvBase;
+
+       psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
+
+       if (psStream) {
+               return ((IMG_VOID *) psStream);
+       }
+
+       psStream = HostNonPageablePageAlloc(1);
+       psInitStream = HostNonPageablePageAlloc(1);
+       psLFBuffer = HostNonPageablePageAlloc(1);
+       if ((!psStream) || (!psInitStream) || (!psLFBuffer)
+           ) {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DBGDriv: Couldn't create buffer !!!!!\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 create buffer !!!!!\n\r"));
+               HostNonPageablePageFree(psStream);
+               return ((IMG_VOID *) 0);
+       }
+
+       psStream->psNext = 0;
+       psStream->ui32Flags = ui32Flags;
+       psStream->ui32Base = (IMG_UINT32) pvBase;
+       psStream->ui32Size = ui32Size * 4096;
+       psStream->ui32RPtr = 0;
+       psStream->ui32WPtr = 0;
+       psStream->ui32DataWritten = 0;
+       psStream->ui32CapMode = ui32CapMode;
+       psStream->ui32OutMode = ui32OutMode;
+       psStream->ui32DebugLevel = DEBUG_LEVEL_0;
+       psStream->ui32DefaultMode = ui32CapMode;
+       psStream->ui32Start = 0;
+       psStream->ui32End = 0;
+       psStream->ui32Current = 0;
+       psStream->ui32SampleRate = 1;
+       psStream->ui32Access = 0;
+       psStream->ui32Timeout = 0;
+       psStream->ui32Marker = 0;
+       psStream->bInitPhaseComplete = IMG_FALSE;
+
+       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 create buffer !!!!!\n\r"));
+
+               if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0) {
+                       HostNonPageablePageFree((IMG_VOID *) psStream->
+                                               ui32Base);
+               } else {
+                       HostPageablePageFree((IMG_VOID *) psStream->ui32Base);
+               }
+               HostNonPageablePageFree(psStream);
+               return ((IMG_VOID *) 0);
+       }
+
+       psInitStream->psNext = 0;
+       psInitStream->ui32Flags = ui32Flags;
+       psInitStream->ui32Base = (IMG_UINT32) pvBase;
+       psInitStream->ui32Size = ui32Size * 4096;
+       psInitStream->ui32RPtr = 0;
+       psInitStream->ui32WPtr = 0;
+       psInitStream->ui32DataWritten = 0;
+       psInitStream->ui32CapMode = ui32CapMode;
+       psInitStream->ui32OutMode = ui32OutMode;
+       psInitStream->ui32DebugLevel = DEBUG_LEVEL_0;
+       psInitStream->ui32DefaultMode = ui32CapMode;
+       psInitStream->ui32Start = 0;
+       psInitStream->ui32End = 0;
+       psInitStream->ui32Current = 0;
+       psInitStream->ui32SampleRate = 1;
+       psInitStream->ui32Access = 0;
+       psInitStream->ui32Timeout = 0;
+       psInitStream->ui32Marker = 0;
+       psInitStream->bInitPhaseComplete = IMG_FALSE;
+
+       psStream->psInitStream = psInitStream;
+
+       psLFBuffer->psStream = psStream;
+       psLFBuffer->ui32BufLen = 0;
+
+       g_bHotkeyMiddump = IMG_FALSE;
+       g_ui32HotkeyMiddumpStart = 0xffffffff;
+       g_ui32HotkeyMiddumpEnd = 0xffffffff;
+
+       ui32Off = 0;
+
+       do {
+               psStream->szName[ui32Off] = pszName[ui32Off];
+
+               ui32Off++;
+       }
+       while ((pszName[ui32Off] != 0)
+              && (ui32Off < (4096 - sizeof(DBG_STREAM))));
+
+       psStream->szName[ui32Off] = pszName[ui32Off];
+
+       psStream->psNext = g_psStreamList;
+       g_psStreamList = psStream;
+
+       psLFBuffer->psNext = g_psLFBufferList;
+       g_psLFBufferList = psLFBuffer;
+
+       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;
+       }
+
+       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->ui32CapMode & DEBUG_CAPMODE_HOTKEY) {
+               DeactivateHotKeys();
+       }
+
+       if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0) {
+               HostNonPageablePageFree((IMG_VOID *) psStream->ui32Base);
+               HostNonPageablePageFree((IMG_VOID *) psStream->psInitStream->
+                                       ui32Base);
+       } else {
+               HostPageablePageFree((IMG_VOID *) psStream->ui32Base);
+               HostPageablePageFree((IMG_VOID *) psStream->psInitStream->
+                                    ui32Base);
+       }
+
+       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;
+
+       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 char szComment[] = "-- Init phase terminated\r\n";
+               psStream->psInitStream->ui32RPtr = 0;
+               psStream->ui32RPtr = 0;
+               psStream->ui32WPtr = 0;
+               psStream->ui32DataWritten =
+                   psStream->psInitStream->ui32DataWritten;
+               if (psStream->bInitPhaseComplete == IMG_FALSE) {
+                       if (psStream->ui32Flags & DEBUG_FLAGS_TEXTSTREAM) {
+                               DBGDrivWrite2(psStream, (IMG_UINT8 *) szComment,
+                                             sizeof(szComment) - 1, 0x01);
+                       }
+                       psStream->bInitPhaseComplete = IMG_TRUE;
+               }
+       }
+
+       return ((IMG_VOID *) psStream);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,
+                                            IMG_CHAR * pszString,
+                                            IMG_UINT32 ui32Level)
+{
+
+       if (!StreamValid(psStream)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+               if (!(psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE)) {
+                       return (0);
+               }
+       } else {
+               if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY) {
+                       if ((psStream->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 (!StreamValid(psStream)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (!(psStream->ui32DebugLevel & ui32Level)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (!(psStream->ui32OutMode & DEBUG_OUTMODE_ASYNC)) {
+               if (psStream->ui32OutMode & DEBUG_OUTMODE_STANDARDDBG) {
+                       PVR_DPF((PVR_DBG_MESSAGE, "%s: %s\r\n",
+                                psStream->szName, pszString));
+               }
+
+               if (psStream->ui32OutMode & DEBUG_OUTMODE_MONO) {
+                       MonoOut(psStream->szName, IMG_FALSE);
+                       MonoOut(": ", IMG_FALSE);
+                       MonoOut(pszString, IMG_TRUE);
+               }
+       }
+
+       if (!((psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) ||
+             (psStream->ui32OutMode & DEBUG_OUTMODE_ASYNC)
+           )
+           ) {
+               return (0xFFFFFFFF);
+       }
+
+       ui32Space = SpaceInStream(psStream);
+
+       if (ui32Space > 0) {
+               ui32Space--;
+       }
+
+       ui32Len = 0;
+       ui32WPtr = psStream->ui32WPtr;
+       pui8Buffer = (IMG_UINT8 *) psStream->ui32Base;
+
+       while ((pszString[ui32Len] != 0) && (ui32Len < ui32Space)) {
+               pui8Buffer[ui32WPtr] = pszString[ui32Len];
+               ui32Len++;
+               ui32WPtr++;
+               if (ui32WPtr == psStream->ui32Size) {
+                       ui32WPtr = 0;
+               }
+       }
+
+       if (ui32Len < ui32Space) {
+
+               pui8Buffer[ui32WPtr] = pszString[ui32Len];
+               ui32Len++;
+               ui32WPtr++;
+               if (ui32WPtr == psStream->ui32Size) {
+                       ui32WPtr = 0;
+               }
+
+               psStream->ui32WPtr = ui32WPtr;
+               psStream->ui32DataWritten += ui32Len;
+       } else {
+               ui32Len = 0;
+       }
+
+       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 (!StreamValid(psStream)) {
+               return (0);
+       }
+
+       pui8Buff = (IMG_UINT8 *) psStream->ui32Base;
+       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] = pui8Buff[ui32Offset];
+               ui32Offset++;
+               ui32Len++;
+
+               if (ui32Offset == psStream->ui32Size) {
+                       ui32Offset = 0;
+               }
+       }
+
+       pszString[ui32Len] = 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 (!StreamValid(psMainStream)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (!(psMainStream->ui32DebugLevel & ui32Level)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (psMainStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+               if (!(psMainStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE)) {
+                       return (0xFFFFFFFF);
+               }
+       } else if (psMainStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY) {
+               if ((psMainStream->ui32Current != g_ui32HotKeyFrame)
+                   || (g_bHotKeyPressed == IMG_FALSE))
+                       return (0xFFFFFFFF);
+       }
+
+       if (psMainStream->bInitPhaseComplete) {
+               psStream = psMainStream;
+       } else {
+               psStream = psMainStream->psInitStream;
+       }
+
+       ui32Space = SpaceInStream(psStream);
+
+       if (!(psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE)) {
+               return (0);
+       }
+
+       if (ui32Space < 8) {
+               return (0);
+       }
+
+       if (ui32Space <= (ui32InBuffSize + 4)) {
+               ui32InBuffSize = ui32Space - 8;
+       }
+
+       Write(psStream, (IMG_UINT8 *) & ui32InBuffSize, 4);
+       Write(psStream, pui8InBuf, ui32InBuffSize);
+
+       return (ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,
+                                      IMG_UINT8 * pui8InBuf,
+                                      IMG_UINT32 ui32InBuffSize,
+                                      IMG_UINT32 ui32Level)
+{
+
+       if (!StreamValid(psStream)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+               if (!(psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE)) {
+                       return (0xFFFFFFFF);
+               }
+       } else {
+               if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY) {
+                       if ((psStream->ui32Current != g_ui32HotKeyFrame)
+                           || (g_bHotKeyPressed == IMG_FALSE)) {
+                               return (0xFFFFFFFF);
+                       }
+               }
+       }
+
+       return (DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level));
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psMainStream,
+                                     IMG_UINT8 * pui8InBuf,
+                                     IMG_UINT32 ui32InBuffSize,
+                                     IMG_UINT32 ui32Level)
+{
+       IMG_UINT32 ui32Space;
+       DBG_STREAM *psStream;
+
+       if (!StreamValid(psMainStream)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (!(psMainStream->ui32DebugLevel & ui32Level)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (psMainStream->bInitPhaseComplete) {
+               psStream = psMainStream;
+       } else {
+               psStream = psMainStream->psInitStream;
+       }
+
+       ui32Space = SpaceInStream(psStream);
+
+       if (!(psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE)) {
+               return (0);
+       }
+
+       if (psStream->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION) {
+
+               if (ui32Space < 32) {
+                       return (0);
+               }
+       } else {
+               if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4))) {
+                       IMG_UINT32 ui32NewBufSize;
+
+                       ui32NewBufSize = 2 * psStream->ui32Size;
+
+                       if (ui32InBuffSize > psStream->ui32Size) {
+                               ui32NewBufSize += ui32InBuffSize;
+                       }
+
+                       if (!ExpandStreamBuffer(psStream, ui32NewBufSize)) {
+                               if (ui32Space < 32) {
+                                       return (0);
+                               }
+                       }
+
+                       ui32Space = SpaceInStream(psStream);
+               }
+       }
+
+       if (ui32Space <= (ui32InBuffSize + 4)) {
+               ui32InBuffSize = ui32Space - 4;
+       }
+
+       Write(psStream, pui8InBuf, ui32InBuffSize);
+
+       return (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 (!StreamValid(psMainStream)) {
+               return (0);
+       }
+
+       if (bReadInitBuffer) {
+               psStream = psMainStream->psInitStream;
+       } else {
+               psStream = psMainStream;
+       }
+
+       if (psStream->ui32RPtr == psStream->ui32WPtr) {
+               return (0);
+       }
+
+       if (psStream->ui32RPtr <= psStream->ui32WPtr) {
+               ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
+       } else {
+               ui32Data =
+                   psStream->ui32WPtr + (psStream->ui32Size -
+                                         psStream->ui32RPtr);
+       }
+
+       if (ui32Data > ui32OutBuffSize) {
+               ui32Data = ui32OutBuffSize;
+       }
+
+       if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size) {
+               IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
+               IMG_UINT32 ui32B2 = ui32Data - ui32B1;
+
+               HostMemCopy((IMG_VOID *) pui8OutBuf,
+                           (IMG_VOID *) (psStream->ui32Base +
+                                         psStream->ui32RPtr), ui32B1);
+
+               HostMemCopy((IMG_VOID *) ((IMG_UINT32) pui8OutBuf + ui32B1),
+                           (IMG_VOID *) psStream->ui32Base, ui32B2);
+
+               psStream->ui32RPtr = ui32B2;
+       } else {
+               HostMemCopy((IMG_VOID *) pui8OutBuf,
+                           (IMG_VOID *) (psStream->ui32Base +
+                                         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->ui32CapMode = ui32Mode;
+       psStream->ui32DefaultMode = ui32Mode;
+       psStream->ui32Start = ui32Start;
+       psStream->ui32End = ui32End;
+       psStream->ui32SampleRate = ui32SampleRate;
+
+       if (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY) {
+               ActivateHotKeys(psStream);
+       }
+}
+
+void IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,
+                                      IMG_UINT32 ui32OutMode)
+{
+
+       if (!StreamValid(psStream)) {
+               return;
+       }
+
+       psStream->ui32OutMode = ui32OutMode;
+}
+
+void IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,
+                                      IMG_UINT32 ui32DebugLevel)
+{
+
+       if (!StreamValid(psStream)) {
+               return;
+       }
+
+       psStream->ui32DebugLevel = ui32DebugLevel;
+}
+
+void IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+
+       if (!StreamValid(psStream)) {
+               return;
+       }
+
+       psStream->ui32Current = ui32Frame;
+
+       if ((ui32Frame >= psStream->ui32Start) &&
+           (ui32Frame <= psStream->ui32End) &&
+           (((ui32Frame - psStream->ui32Start) % psStream->ui32SampleRate) ==
+            0)) {
+               psStream->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+       } else {
+               psStream->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+       }
+
+       if (g_bHotkeyMiddump) {
+               if ((ui32Frame >= g_ui32HotkeyMiddumpStart) &&
+                   (ui32Frame <= g_ui32HotkeyMiddumpEnd) &&
+                   (((ui32Frame -
+                      g_ui32HotkeyMiddumpStart) % psStream->ui32SampleRate) ==
+                    0)) {
+                       psStream->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+               } else {
+                       psStream->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+                       if (psStream->ui32Current > g_ui32HotkeyMiddumpEnd) {
+                               g_bHotkeyMiddump = IMG_FALSE;
+                       }
+               }
+       }
+
+       if (g_bHotKeyRegistered) {
+               g_bHotKeyRegistered = IMG_FALSE;
+
+               PVR_DPF((PVR_DBG_MESSAGE, "Hotkey pressed (%08x)!\n",
+                        psStream));
+
+               if (!g_bHotKeyPressed) {
+
+                       g_ui32HotKeyFrame = psStream->ui32Current + 2;
+
+                       g_bHotKeyPressed = IMG_TRUE;
+               }
+
+               if ((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+                   && (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY)) {
+                       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->ui32SampleRate));
+                       } else {
+
+                               g_ui32HotkeyMiddumpEnd = g_ui32HotKeyFrame;
+                               PVR_DPF((PVR_DBG_MESSAGE,
+                                        "Turning off sampling\n"));
+                       }
+               }
+
+       }
+
+       if (psStream->ui32Current > g_ui32HotKeyFrame) {
+               g_bHotKeyPressed = IMG_FALSE;
+       }
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream)
+{
+
+       if (!StreamValid(psStream)) {
+               return (0);
+       }
+
+       return (psStream->ui32Current);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+       IMG_UINT32 ui32NextFrame;
+
+       if (!StreamValid(psStream)) {
+               return IMG_FALSE;
+       }
+
+       if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+               ui32NextFrame =
+                   psStream->ui32Current + psStream->ui32SampleRate;
+               if (ui32NextFrame > psStream->ui32End) {
+                       return IMG_TRUE;
+               }
+       }
+       return IMG_FALSE;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream,
+                                             IMG_BOOL bCheckPreviousFrame)
+{
+       IMG_UINT32 ui32FrameShift = bCheckPreviousFrame ? 1 : 0;
+
+       if (!StreamValid(psStream)) {
+               return IMG_FALSE;
+       }
+
+       if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+
+               if (g_bHotkeyMiddump) {
+                       if ((psStream->ui32Current >=
+                            (g_ui32HotkeyMiddumpStart - ui32FrameShift))
+                           && (psStream->ui32Current <=
+                               (g_ui32HotkeyMiddumpEnd - ui32FrameShift))
+                           &&
+                           ((((psStream->ui32Current + ui32FrameShift) -
+                              g_ui32HotkeyMiddumpStart) %
+                             psStream->ui32SampleRate) == 0)) {
+                               return IMG_TRUE;
+                       }
+               } else {
+                       if ((psStream->ui32Current >=
+                            (psStream->ui32Start - ui32FrameShift))
+                           && (psStream->ui32Current <=
+                               (psStream->ui32End - ui32FrameShift))
+                           &&
+                           ((((psStream->ui32Current + ui32FrameShift) -
+                              psStream->ui32Start) %
+                             psStream->ui32SampleRate) == 0)) {
+                               return IMG_TRUE;
+                       }
+               }
+       } else if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY) {
+               if ((psStream->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->ui32CapMode = ui32Mode;
+}
+
+void IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+       if (!StreamValid(psStream)) {
+               return;
+       }
+
+       psStream->ui32CapMode = psStream->ui32DefaultMode;
+}
+
+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->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->bInitPhaseComplete) {
+               psStream = psMainStream;
+       } else {
+               psStream = psMainStream->psInitStream;
+       }
+
+       psStream->ui32DataWritten = ui32StreamOffset;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetServiceTable(void)
+{
+       return ((IMG_UINT32) & 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 (!StreamValid(psStream)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (!(psStream->ui32DebugLevel & ui32Level)) {
+               return (0xFFFFFFFF);
+       }
+
+       if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+               if (!(psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE)) {
+                       return (0xFFFFFFFF);
+               }
+       } else if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY) {
+               if ((psStream->ui32Current != g_ui32HotKeyFrame)
+                   || (g_bHotKeyPressed == IMG_FALSE))
+                       return (0xFFFFFFFF);
+       }
+
+       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 (!StreamValid(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 DBGDrivEndInitPhase(PDBG_STREAM psStream)
+{
+       psStream->bInitPhaseComplete = IMG_TRUE;
+}
+
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
+{
+       IMG_VOID *pvNewBuf;
+       IMG_UINT32 ui32NewSizeInPages;
+       IMG_UINT32 ui32NewWOffset;
+       IMG_UINT32 ui32SpaceInOldBuf;
+
+       if (psStream->ui32Size >= ui32NewSize) {
+               return IMG_FALSE;
+       }
+
+       ui32SpaceInOldBuf = SpaceInStream(psStream);
+
+       ui32NewSizeInPages = ((ui32NewSize + 0xfff) & ~0xfff) / 4096;
+
+       if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0) {
+               pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
+       } else {
+               pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
+       }
+
+       if (pvNewBuf == IMG_NULL) {
+               return IMG_FALSE;
+       }
+
+       if (psStream->ui32RPtr <= psStream->ui32WPtr) {
+
+               HostMemCopy((IMG_VOID *) pvNewBuf,
+                           (IMG_VOID *) (psStream->ui32Base +
+                                         psStream->ui32RPtr),
+                           psStream->ui32WPtr - psStream->ui32RPtr);
+       } else {
+               IMG_UINT32 ui32FirstCopySize;
+
+               ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
+
+               HostMemCopy((IMG_VOID *) pvNewBuf,
+                           (IMG_VOID *) (psStream->ui32Base +
+                                         psStream->ui32RPtr),
+                           ui32FirstCopySize);
+
+               HostMemCopy((IMG_VOID *) ((IMG_UINT32) pvNewBuf +
+                                         ui32FirstCopySize),
+                           (IMG_VOID *) psStream->ui32Base,
+                           psStream->ui32WPtr);
+       }
+
+       ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
+
+       if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0) {
+               HostNonPageablePageFree((IMG_VOID *) psStream->ui32Base);
+       } else {
+               HostPageablePageFree((IMG_VOID *) psStream->ui32Base);
+       }
+
+       psStream->ui32Base = (IMG_UINT32) pvNewBuf;
+       psStream->ui32RPtr = 0;
+       psStream->ui32WPtr = ui32NewWOffset;
+       psStream->ui32Size = ui32NewSizeInPages * 4096;
+
+       return IMG_TRUE;
+}
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
+{
+       IMG_UINT32 ui32Space;
+
+       if (psStream->ui32RPtr > psStream->ui32WPtr) {
+               ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
+       } else {
+               ui32Space =
+                   psStream->ui32RPtr + (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/pvr/tools/dbgdriv.h b/pvr/tools/dbgdriv.h
new file mode 100644 (file)
index 0000000..020b59c
--- /dev/null
@@ -0,0 +1,186 @@
+/**********************************************************************
+ *
+ * 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_UINT32 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 DBGDrivSetMarker(PDBG_STREAM psStream,
+                                      IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_UINT32 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 DBGDrivEndInitPhase(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psStream,
+                                            IMG_UINT32 ui32StreamOffset);
+
+IMG_VOID DestroyAllStreams(IMG_VOID);
+
+IMG_UINT32 AtoI(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_BOOL StreamValid(PDBG_STREAM psStream);
+IMG_VOID Write(PDBG_STREAM psStream, IMG_UINT8 * pui8Data,
+              IMG_UINT32 ui32InBuffSize);
+IMG_VOID MonoOut(IMG_CHAR * pszString, IMG_BOOL bNewLine);
+
+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 ExtDBGDrivEndInitPhase(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_UINT32 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);
+
+#endif
diff --git a/pvr/tools/hostfunc.c b/pvr/tools/hostfunc.c
new file mode 100644 (file)
index 0000000..036f649
--- /dev/null
@@ -0,0 +1,205 @@
+/**********************************************************************
+ *
+ * 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/mm.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+
+#include "img_types.h"
+#include "pvr_debug.h"
+
+IMG_UINT32 gPVRDebugLevel = 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, bDebug;
+#if !defined(__sh__)
+       IMG_CHAR *pszLeafName;
+
+       pszLeafName = (char *)strrchr(pszFileName, '\\');
+
+       if (pszLeafName) {
+               pszFileName = pszLeafName;
+       }
+#endif
+
+       bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+       bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+       if (bTrace || bDebug) {
+               va_list vaArgs;
+               static char szBuffer[256];
+
+               va_start(vaArgs, pszFormat);
+
+               if (bDebug) {
+                       switch (ui32DebugLevel) {
+                       case DBGPRIV_FATAL:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Fatal): ");
+                                       break;
+                               }
+                       case DBGPRIV_ERROR:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Error): ");
+                                       break;
+                               }
+                       case DBGPRIV_WARNING:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Warning): ");
+                                       break;
+                               }
+                       case DBGPRIV_MESSAGE:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Message): ");
+                                       break;
+                               }
+                       case DBGPRIV_VERBOSE:
+                               {
+                                       strcpy(szBuffer, "PVR_K:(Verbose): ");
+                                       break;
+                               }
+                       default:
+                               {
+                                       strcpy(szBuffer,
+                                              "PVR_K:(Unknown message level)");
+                                       break;
+                               }
+                       }
+               } else {
+                       strcpy(szBuffer, "PVR_K: ");
+               }
+
+               vsprintf(&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
+
+               if (!bTrace) {
+                       sprintf(&szBuffer[strlen(szBuffer)], " [%d, %s]",
+                               (int)ui32Line, pszFileName);
+               }
+
+               printk(KERN_INFO "%s\r\n", szBuffer);
+
+               va_end(vaArgs);
+       }
+}
+
+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)
+{
+
+       return IMG_NULL;
+}
+
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex)
+{
+
+}
+
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex)
+{
+
+}
+
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex)
+{
+
+}
diff --git a/pvr/tools/hostfunc.h b/pvr/tools/hostfunc.h
new file mode 100644 (file)
index 0000000..3e855de
--- /dev/null
@@ -0,0 +1,53 @@
+/**********************************************************************
+ *
+ * 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(char *pcKey, 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);
+
+#endif
diff --git a/pvr/tools/hotkey.c b/pvr/tools/hotkey.c
new file mode 100644 (file)
index 0000000..4319020
--- /dev/null
@@ -0,0 +1,116 @@
+/**********************************************************************
+ *
+ * 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->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/pvr/tools/hotkey.h b/pvr/tools/hotkey.h
new file mode 100644 (file)
index 0000000..5d18632
--- /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 _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/pvr/tools/ioctl.c b/pvr/tools/ioctl.c
new file mode 100644 (file)
index 0000000..2ff9af9
--- /dev/null
@@ -0,0 +1,416 @@
+/**********************************************************************
+ *
+ * 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"
+
+IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID * pvInBuffer,
+                                  IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_CREATESTREAM psIn;
+       IMG_VOID **ppvOut;
+#ifdef LINUX
+       static char name[32];
+#endif
+
+       psIn = (PDBG_IN_CREATESTREAM) pvInBuffer;
+       ppvOut = (IMG_VOID * *)pvOutBuffer;
+
+#ifdef LINUX
+
+       if (copy_from_user(name, psIn->pszName, 32) != 0)
+               return IMG_FALSE;
+       *ppvOut =
+           ExtDBGDrivCreateStream(name, psIn->ui32CapMode, psIn->ui32OutMode,
+                                  0, psIn->ui32Pages);
+
+#else
+       *ppvOut =
+           ExtDBGDrivCreateStream(psIn->pszName, psIn->ui32CapMode,
+                                  psIn->ui32OutMode,
+                                  DEBUG_FLAGS_NO_BUF_EXPANDSION,
+                                  psIn->ui32Pages);
+#endif
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID * pvInBuffer,
+                                   IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pStream;
+       PDBG_STREAM psStream;
+
+       pStream = (IMG_UINT32 *) pvInBuffer;
+       psStream = (PDBG_STREAM) * pStream;
+
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivDestroyStream(psStream);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_FINDSTREAM psParams;
+       IMG_UINT32 *pui32Stream;
+
+       psParams = (PDBG_IN_FINDSTREAM) pvInBuffer;
+       pui32Stream = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32Stream =
+           (IMG_UINT32) ExtDBGDrivFindStream(psParams->pszName,
+                                             psParams->bResetStream);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_WRITESTRING psParams;
+       IMG_UINT32 *pui32OutLen;
+
+       psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+       pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32OutLen =
+           ExtDBGDrivWriteString((PDBG_STREAM) psParams->pvStream,
+                                 psParams->pszString, psParams->ui32Level);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID * pvInBuffer,
+                                   IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_WRITESTRING psParams;
+       IMG_UINT32 *pui32OutLen;
+
+       psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+       pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32OutLen =
+           ExtDBGDrivWriteStringCM((PDBG_STREAM) psParams->pvStream,
+                                   psParams->pszString, psParams->ui32Level);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pui32OutLen;
+       PDBG_IN_READSTRING psParams;
+
+       psParams = (PDBG_IN_READSTRING) pvInBuffer;
+       pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32OutLen =
+           ExtDBGDrivReadString(psParams->pvStream, psParams->pszString,
+                                psParams->ui32StringLen);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pui32BytesCopied;
+       PDBG_IN_WRITE psInParams;
+
+       psInParams = (PDBG_IN_WRITE) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32BytesCopied =
+           ExtDBGDrivWrite((PDBG_STREAM) psInParams->pvStream,
+                           psInParams->pui8InBuffer,
+                           psInParams->ui32TransferSize,
+                           psInParams->ui32Level);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pui32BytesCopied;
+       PDBG_IN_WRITE psInParams;
+
+       psInParams = (PDBG_IN_WRITE) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32BytesCopied =
+           ExtDBGDrivWrite2((PDBG_STREAM) psInParams->pvStream,
+                            psInParams->pui8InBuffer,
+                            psInParams->ui32TransferSize,
+                            psInParams->ui32Level);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pui32BytesCopied;
+       PDBG_IN_WRITE psInParams;
+
+       psInParams = (PDBG_IN_WRITE) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32BytesCopied =
+           ExtDBGDrivWriteCM((PDBG_STREAM) psInParams->pvStream,
+                             psInParams->pui8InBuffer,
+                             psInParams->ui32TransferSize,
+                             psInParams->ui32Level);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivRead(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pui32BytesCopied;
+       PDBG_IN_READ psInParams;
+
+       psInParams = (PDBG_IN_READ) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32BytesCopied =
+           ExtDBGDrivRead((PDBG_STREAM) psInParams->pvStream,
+                          psInParams->bReadInitBuffer,
+                          psInParams->ui32OutBufferSize,
+                          psInParams->pui8OutBuffer);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID * pvInBuffer,
+                                    IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETDEBUGMODE psParams;
+
+       psParams = (PDBG_IN_SETDEBUGMODE) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivSetCaptureMode((PDBG_STREAM) psParams->pvStream,
+                                psParams->ui32Mode,
+                                psParams->ui32Start,
+                                psParams->ui32End, psParams->ui32SampleRate);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETDEBUGOUTMODE psParams;
+
+       psParams = (PDBG_IN_SETDEBUGOUTMODE) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivSetOutputMode((PDBG_STREAM) psParams->pvStream,
+                               psParams->ui32Mode);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID * pvInBuffer,
+                                   IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETDEBUGLEVEL psParams;
+
+       psParams = (PDBG_IN_SETDEBUGLEVEL) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivSetDebugLevel((PDBG_STREAM) psParams->pvStream,
+                               psParams->ui32Level);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETFRAME psParams;
+
+       psParams = (PDBG_IN_SETFRAME) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivSetFrame((PDBG_STREAM) psParams->pvStream,
+                          psParams->ui32Frame);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pStream;
+       PDBG_STREAM psStream;
+       IMG_UINT32 *pui32Current;
+
+       pStream = (IMG_UINT32 *) pvInBuffer;
+       psStream = (PDBG_STREAM) * pStream;
+       pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32Current = ExtDBGDrivGetFrame(psStream);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID * pvInBuffer,
+                                    IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_ISCAPTUREFRAME psParams;
+       IMG_UINT32 *pui32Current;
+
+       psParams = (PDBG_IN_ISCAPTUREFRAME) pvInBuffer;
+       pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32Current =
+           ExtDBGDrivIsCaptureFrame((PDBG_STREAM) psParams->pvStream,
+                                    psParams->bCheckPreviousFrame);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID * pvInBuffer,
+                                  IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_OVERRIDEMODE psParams;
+
+       psParams = (PDBG_IN_OVERRIDEMODE) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivOverrideMode((PDBG_STREAM) psParams->pvStream,
+                              psParams->ui32Mode);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pStream;
+       PDBG_STREAM psStream;
+
+       pStream = (IMG_UINT32 *) pvInBuffer;
+       psStream = (PDBG_STREAM) * pStream;
+
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivDefaultMode(psStream);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_SETMARKER psParams;
+
+       psParams = (PDBG_IN_SETMARKER) pvInBuffer;
+       PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+       ExtDBGDrivSetMarker((PDBG_STREAM) psParams->pvStream,
+                           psParams->ui32Marker);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pStream;
+       PDBG_STREAM psStream;
+       IMG_UINT32 *pui32Current;
+
+       pStream = (IMG_UINT32 *) pvInBuffer;
+       psStream = (PDBG_STREAM) * pStream;
+       pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32Current = ExtDBGDrivGetMarker(psStream);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID * pvInBuffer,
+                                     IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pui32Out;
+
+       PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+       pui32Out = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32Out = DBGDrivGetServiceTable();
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       PDBG_IN_WRITE_LF psInParams;
+       IMG_UINT32 *pui32BytesCopied;
+
+       psInParams = (PDBG_IN_WRITE_LF) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32BytesCopied = ExtDBGDrivWriteLF(psInParams->pvStream,
+                                             psInParams->pui8InBuffer,
+                                             psInParams->ui32BufferSize,
+                                             psInParams->ui32Level,
+                                             psInParams->ui32Flags);
+
+       return IMG_TRUE;
+}
+
+IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pui32BytesCopied;
+       PDBG_IN_READ psInParams;
+
+       psInParams = (PDBG_IN_READ) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32BytesCopied =
+           ExtDBGDrivReadLF((PDBG_STREAM) psInParams->pvStream,
+                            psInParams->ui32OutBufferSize,
+                            psInParams->pui8OutBuffer);
+
+       return (IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivResetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+       IMG_UINT32 *pui32BytesCopied;
+       PDBG_IN_READ psInParams;
+
+       psInParams = (PDBG_IN_READ) pvInBuffer;
+       pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+       *pui32BytesCopied =
+           ExtDBGDrivReadLF((PDBG_STREAM) psInParams->pvStream,
+                            psInParams->ui32OutBufferSize,
+                            psInParams->pui8OutBuffer);
+
+       return (IMG_TRUE);
+}
diff --git a/pvr/tools/ioctl.h b/pvr/tools/ioctl.h
new file mode 100644 (file)
index 0000000..ea207a2
--- /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 _IOCTL_
+#define _IOCTL_
+
+IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivRead(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivResetStream(IMG_VOID *, IMG_VOID *);
+
+IMG_UINT32(*g_DBGDrivProc[])(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, DBGDIOCDrivResetStream,};
+
+#define MAX_DBGVXD_W32_API (sizeof(g_DBGDrivProc)/sizeof(IMG_UINT32))
+
+#endif
diff --git a/pvr/tools/linuxsrv.h b/pvr/tools/linuxsrv.h
new file mode 100644 (file)
index 0000000..72a1245
--- /dev/null
@@ -0,0 +1,47 @@
+/**********************************************************************
+ *
+ * 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/pvr/tools/main.c b/pvr/tools/main.c
new file mode 100644 (file)
index 0000000..a1445d1
--- /dev/null
@@ -0,0 +1,184 @@
+/**********************************************************************
+ *
+ * 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 <asm/uaccess.h>
+
+#include "img_types.h"
+#include "linuxsrv.h"
+#include "ioctl.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hostfunc.h"
+#include "pvr_debug.h"
+
+#define DRVNAME "dbgdrv"
+
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+
+static int AssignedMajorNumber = 0;
+
+extern DBGKM_SERVICE_TABLE g_sDBGKMServices;
+
+int dbgdrv_ioctl(struct inode *, 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,
+ioctl: dbgdrv_ioctl,
+open:  dbgdrv_open,
+release:dbgdrv_release,
+mmap:  dbgdrv_mmap,
+};
+
+void DBGDrvGetServiceTable(void **fn_table)
+{
+       *fn_table = &g_sDBGKMServices;
+
+}
+
+int init_module(void)
+{
+       AssignedMajorNumber =
+           register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
+
+       if (AssignedMajorNumber <= 0) {
+               PVR_DPF((PVR_DBG_ERROR, " unable to get major\n"));
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       unregister_chrdev(AssignedMajorNumber, DRVNAME);
+       return;
+}
+
+int dbgdrv_ioctl(struct inode *inode, struct file *file,
+                unsigned int cmd, unsigned long arg)
+{
+       IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
+
+       char *buffer, *in, *out;
+
+       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_CHAR *ui8Tmp;
+               IMG_UINT32 *pui32BytesCopied = (IMG_UINT32 *) out;
+               DBG_IN_READ *psReadInParams = (DBG_IN_READ *) in;
+
+               ui8Tmp = vmalloc(psReadInParams->ui32OutBufferSize);
+               if (!ui8Tmp) {
+                       goto init_failed;
+               }
+               *pui32BytesCopied =
+                   ExtDBGDrivRead((DBG_STREAM *) psReadInParams->pvStream,
+                                  psReadInParams->bReadInitBuffer,
+                                  psReadInParams->ui32OutBufferSize, ui8Tmp);
+               if (copy_to_user
+                   (psReadInParams->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;
+}
+
+void RemoveHotKey(unsigned hHotKey)
+{
+
+}
+
+void DefineHotKey(unsigned ScanCode, unsigned ShiftState, void *pInfo)
+{
+
+}
+
+EXPORT_SYMBOL(DBGDrvGetServiceTable);