From ba7179ec3604c4352cc901e8423d3650f7b05a68 Mon Sep 17 00:00:00 2001 From: Imagination Technologies/TI Date: Sat, 19 May 2012 15:47:09 +0300 Subject: [PATCH 1/1] 1.3.13.1607/3_00_00_08+flat+Lindent --- pvr/COPYING | 351 ++ pvr/INSTALL | 76 + pvr/Kbuild | 53 + pvr/Makefile | 157 + pvr/README | 48 + pvr/bridged_pvr_bridge.c | 5017 +++++++++++++++++++++++++++++ pvr/bridged_pvr_bridge.h | 86 + pvr/buffer_manager.c | 1574 +++++++++ pvr/buffer_manager.h | 180 ++ pvr/bufferclass_example.c | 284 ++ pvr/bufferclass_example.h | 132 + pvr/bufferclass_example_linux.c | 289 ++ pvr/bufferclass_example_linux.h | 45 + pvr/bufferclass_example_private.c | 226 ++ pvr/dbgdrvif.h | 283 ++ pvr/device.h | 251 ++ pvr/deviceclass.c | 1584 +++++++++ pvr/devicemem.c | 1049 ++++++ pvr/env_data.h | 52 + pvr/event.c | 278 ++ pvr/event.h | 35 + pvr/handle.c | 1366 ++++++++ pvr/handle.h | 369 +++ pvr/hash.c | 384 +++ pvr/hash.h | 81 + pvr/img_defs.h | 98 + pvr/img_types.h | 110 + pvr/ioctldef.h | 97 + pvr/kernelbuffer.h | 59 + pvr/kerneldisplay.h | 144 + pvr/mem.c | 121 + pvr/metrics.c | 144 + pvr/metrics.h | 112 + pvr/mm.c | 1756 ++++++++++ pvr/mm.h | 288 ++ pvr/mmap.c | 689 ++++ pvr/mmap.h | 70 + pvr/mmu.c | 1926 +++++++++++ pvr/mmu.h | 103 + pvr/module.c | 522 +++ pvr/modules.order | 2 + pvr/mutex.c | 127 + pvr/mutex.h | 65 + pvr/oemfuncs.h | 54 + pvr/omaplfb.h | 208 ++ pvr/omaplfb_displayclass.c | 1356 ++++++++ pvr/omaplfb_linux.c | 373 +++ pvr/osfunc.c | 2161 +++++++++++++ pvr/osfunc.h | 474 +++ pvr/pb.c | 469 +++ pvr/pdump.c | 1397 ++++++++ pvr/pdump_km.h | 300 ++ pvr/pdumpdefs.h | 92 + pvr/perproc.c | 242 ++ pvr/perproc.h | 66 + pvr/power.c | 647 ++++ pvr/power.h | 119 + pvr/proc.c | 360 +++ pvr/proc.h | 51 + pvr/pvr_bridge.h | 1022 ++++++ pvr/pvr_bridge_k.c | 365 +++ pvr/pvr_bridge_km.h | 355 ++ pvr/pvr_debug.c | 187 ++ pvr/pvr_debug.h | 112 + pvr/pvrmmap.h | 36 + pvr/pvrmodule.h | 31 + pvr/pvrsrv.c | 958 ++++++ pvr/pvrversion.h | 37 + pvr/queue.c | 893 +++++ pvr/queue.h | 124 + pvr/ra.c | 1181 +++++++ pvr/ra.h | 130 + pvr/regpaths.h | 41 + pvr/resman.c | 606 ++++ pvr/resman.h | 103 + pvr/services.h | 994 ++++++ pvr/services_headers.h | 48 + pvr/servicesext.h | 398 +++ pvr/servicesint.h | 212 ++ pvr/sgx530defs.h | 427 +++ pvr/sgx_bridge.h | 366 +++ pvr/sgx_bridge_km.h | 152 + pvr/sgxapi_km.h | 206 ++ pvr/sgxconfig.h | 127 + pvr/sgxcoretypes.h | 41 + pvr/sgxdefs.h | 57 + pvr/sgxerrata.h | 191 ++ pvr/sgxfeaturedefs.h | 74 + pvr/sgxinfo.h | 367 +++ pvr/sgxinfokm.h | 268 ++ pvr/sgxinit.c | 1618 ++++++++++ pvr/sgxkick.c | 395 +++ pvr/sgxmmu.h | 56 + pvr/sgxreset.c | 328 ++ pvr/sgxscript.h | 70 + pvr/sgxtransfer.c | 514 +++ pvr/sgxutils.c | 915 ++++++ pvr/sgxutils.h | 128 + pvr/srvkm.h | 52 + pvr/syscommon.h | 192 ++ pvr/sysconfig.c | 737 +++++ pvr/sysconfig.h | 51 + pvr/sysinfo.h | 95 + pvr/syslocal.h | 106 + pvr/sysutils.c | 29 + pvr/sysutils_linux.c | 578 ++++ pvr/tools/dbgdriv.c | 1703 ++++++++++ pvr/tools/dbgdriv.h | 186 ++ pvr/tools/hostfunc.c | 205 ++ pvr/tools/hostfunc.h | 53 + pvr/tools/hotkey.c | 116 + pvr/tools/hotkey.h | 56 + pvr/tools/ioctl.c | 416 +++ pvr/tools/ioctl.h | 81 + pvr/tools/linuxsrv.h | 47 + pvr/tools/main.c | 184 ++ 116 files changed, 48072 insertions(+) create mode 100644 pvr/COPYING create mode 100644 pvr/INSTALL create mode 100644 pvr/Kbuild create mode 100644 pvr/Makefile create mode 100644 pvr/README create mode 100644 pvr/bridged_pvr_bridge.c create mode 100644 pvr/bridged_pvr_bridge.h create mode 100644 pvr/buffer_manager.c create mode 100644 pvr/buffer_manager.h create mode 100644 pvr/bufferclass_example.c create mode 100644 pvr/bufferclass_example.h create mode 100644 pvr/bufferclass_example_linux.c create mode 100644 pvr/bufferclass_example_linux.h create mode 100644 pvr/bufferclass_example_private.c create mode 100644 pvr/dbgdrvif.h create mode 100644 pvr/device.h create mode 100644 pvr/deviceclass.c create mode 100644 pvr/devicemem.c create mode 100644 pvr/env_data.h create mode 100644 pvr/event.c create mode 100644 pvr/event.h create mode 100644 pvr/handle.c create mode 100644 pvr/handle.h create mode 100644 pvr/hash.c create mode 100644 pvr/hash.h create mode 100644 pvr/img_defs.h create mode 100644 pvr/img_types.h create mode 100644 pvr/ioctldef.h create mode 100644 pvr/kernelbuffer.h create mode 100644 pvr/kerneldisplay.h create mode 100644 pvr/mem.c create mode 100644 pvr/metrics.c create mode 100644 pvr/metrics.h create mode 100644 pvr/mm.c create mode 100644 pvr/mm.h create mode 100644 pvr/mmap.c create mode 100644 pvr/mmap.h create mode 100644 pvr/mmu.c create mode 100644 pvr/mmu.h create mode 100644 pvr/module.c create mode 100644 pvr/modules.order create mode 100644 pvr/mutex.c create mode 100644 pvr/mutex.h create mode 100644 pvr/oemfuncs.h create mode 100644 pvr/omaplfb.h create mode 100644 pvr/omaplfb_displayclass.c create mode 100644 pvr/omaplfb_linux.c create mode 100644 pvr/osfunc.c create mode 100644 pvr/osfunc.h create mode 100644 pvr/pb.c create mode 100644 pvr/pdump.c create mode 100644 pvr/pdump_km.h create mode 100644 pvr/pdumpdefs.h create mode 100644 pvr/perproc.c create mode 100644 pvr/perproc.h create mode 100644 pvr/power.c create mode 100644 pvr/power.h create mode 100644 pvr/proc.c create mode 100644 pvr/proc.h create mode 100644 pvr/pvr_bridge.h create mode 100644 pvr/pvr_bridge_k.c create mode 100644 pvr/pvr_bridge_km.h create mode 100644 pvr/pvr_debug.c create mode 100644 pvr/pvr_debug.h create mode 100644 pvr/pvrmmap.h create mode 100644 pvr/pvrmodule.h create mode 100644 pvr/pvrsrv.c create mode 100644 pvr/pvrversion.h create mode 100644 pvr/queue.c create mode 100644 pvr/queue.h create mode 100644 pvr/ra.c create mode 100644 pvr/ra.h create mode 100644 pvr/regpaths.h create mode 100644 pvr/resman.c create mode 100644 pvr/resman.h create mode 100644 pvr/services.h create mode 100644 pvr/services_headers.h create mode 100644 pvr/servicesext.h create mode 100644 pvr/servicesint.h create mode 100644 pvr/sgx530defs.h create mode 100644 pvr/sgx_bridge.h create mode 100644 pvr/sgx_bridge_km.h create mode 100644 pvr/sgxapi_km.h create mode 100644 pvr/sgxconfig.h create mode 100644 pvr/sgxcoretypes.h create mode 100644 pvr/sgxdefs.h create mode 100644 pvr/sgxerrata.h create mode 100644 pvr/sgxfeaturedefs.h create mode 100644 pvr/sgxinfo.h create mode 100644 pvr/sgxinfokm.h create mode 100644 pvr/sgxinit.c create mode 100644 pvr/sgxkick.c create mode 100644 pvr/sgxmmu.h create mode 100644 pvr/sgxreset.c create mode 100644 pvr/sgxscript.h create mode 100644 pvr/sgxtransfer.c create mode 100644 pvr/sgxutils.c create mode 100644 pvr/sgxutils.h create mode 100644 pvr/srvkm.h create mode 100644 pvr/syscommon.h create mode 100644 pvr/sysconfig.c create mode 100644 pvr/sysconfig.h create mode 100644 pvr/sysinfo.h create mode 100644 pvr/syslocal.h create mode 100644 pvr/sysutils.c create mode 100644 pvr/sysutils_linux.c create mode 100644 pvr/tools/dbgdriv.c create mode 100644 pvr/tools/dbgdriv.h create mode 100644 pvr/tools/hostfunc.c create mode 100644 pvr/tools/hostfunc.h create mode 100644 pvr/tools/hotkey.c create mode 100644 pvr/tools/hotkey.h create mode 100644 pvr/tools/ioctl.c create mode 100644 pvr/tools/ioctl.h create mode 100644 pvr/tools/linuxsrv.h create mode 100644 pvr/tools/main.c diff --git a/pvr/COPYING b/pvr/COPYING new file mode 100644 index 0000000..84ac8ec --- /dev/null +++ b/pvr/COPYING @@ -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. + + + Copyright (C) 19yy + + 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. + + , 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 index 0000000..bd08a56 --- /dev/null +++ b/pvr/INSTALL @@ -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 index 0000000..19f9a24 --- /dev/null +++ b/pvr/Kbuild @@ -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 index 0000000..7f5271d --- /dev/null +++ b/pvr/Makefile @@ -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 index 0000000..788a703 --- /dev/null +++ b/pvr/README @@ -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. +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 index 0000000..f651cf7 --- /dev/null +++ b/pvr/bridged_pvr_bridge.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include + +#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 index 0000000..c0130c5 --- /dev/null +++ b/pvr/bridged_pvr_bridge.h @@ -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. + * 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 index 0000000..d293915 --- /dev/null +++ b/pvr/buffer_manager.c @@ -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. + * 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 index 0000000..1523bce --- /dev/null +++ b/pvr/buffer_manager.h @@ -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. + * 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 index 0000000..83cb59a --- /dev/null +++ b/pvr/bufferclass_example.c @@ -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. + * 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 index 0000000..a31aa44 --- /dev/null +++ b/pvr/bufferclass_example.h @@ -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. + * 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 index 0000000..77ff988 --- /dev/null +++ b/pvr/bufferclass_example_linux.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include +#include +#include +#include +#include + +#if defined(LMA) +#include +#else +#include +#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 index 0000000..bbaffee --- /dev/null +++ b/pvr/bufferclass_example_linux.h @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef __BC_EXAMPLE_LINUX_H__ +#define __BC_EXAMPLE_LINUX_H__ + +#include + +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 index 0000000..fb3f1d0 --- /dev/null +++ b/pvr/bufferclass_example_private.c @@ -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. + * 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 index 0000000..cf04501 --- /dev/null +++ b/pvr/dbgdrvif.h @@ -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. + * 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 index 0000000..2eb003d --- /dev/null +++ b/pvr/device.h @@ -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. + * 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 index 0000000..1385115 --- /dev/null +++ b/pvr/deviceclass.c @@ -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. + * 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 index 0000000..88cc6f3 --- /dev/null +++ b/pvr/devicemem.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include + +#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 index 0000000..ecfaa59 --- /dev/null +++ b/pvr/env_data.h @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef _ENV_DATA_ +#define _ENV_DATA_ + +#include +#include + +#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 index 0000000..61bcc5a --- /dev/null +++ b/pvr/event.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) +#include +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..8d609bc --- /dev/null +++ b/pvr/event.h @@ -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. + * 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 index 0000000..ddbb468 --- /dev/null +++ b/pvr/handle.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifdef PVR_SECURE_HANDLES +#include + +#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 index 0000000..cca1cfb --- /dev/null +++ b/pvr/handle.h @@ -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. + * 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 index 0000000..92acdeb --- /dev/null +++ b/pvr/hash.c @@ -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. + * 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 index 0000000..59b7f0a --- /dev/null +++ b/pvr/hash.h @@ -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. + * 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 index 0000000..5cc140c --- /dev/null +++ b/pvr/img_defs.h @@ -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. + * 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 index 0000000..b0ec065 --- /dev/null +++ b/pvr/img_types.h @@ -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. + * 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 index 0000000..c9ae96d --- /dev/null +++ b/pvr/ioctldef.h @@ -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. + * 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 index 0000000..cad6eec --- /dev/null +++ b/pvr/kernelbuffer.h @@ -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. + * 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 index 0000000..2364dca --- /dev/null +++ b/pvr/kerneldisplay.h @@ -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. + * 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 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. + * 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 index 0000000..dab858c --- /dev/null +++ b/pvr/metrics.c @@ -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. + * 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 index 0000000..c41d735 --- /dev/null +++ b/pvr/metrics.h @@ -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. + * 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 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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) +#include +#endif +#include +#include +#include + +#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 +#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, + "\n" + "\t%lu\n" + "\t\n" + "\t\n" + "\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 + "\n" + "\t%8p\n" + "\t%s\n" + "\t%8p\n" + "\t%08lx\n" + "\t%ld\n" + "\t%u\n" + "\t%08lx\n" + "\t%s\n" + "\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, + "\n\n"); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_HighWaterMarkData + [DEBUG_MEM_ALLOC_TYPE_KMALLOC]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_HighWaterMarkData + [DEBUG_MEM_ALLOC_TYPE_VMALLOC]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_WaterMarkData + [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_HighWaterMarkData + [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_HighWaterMarkData + [DEBUG_MEM_ALLOC_TYPE_IOREMAP]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_WaterMarkData + [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_HighWaterMarkData + [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMAP]); + Ret = + printAppend(buffer, count, Ret, + "\n", + g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMAP]); + + Ret = printAppend(buffer, count, Ret, "\n"); + + Ret = printAppend(buffer, count, Ret, + "\n", + g_SysRAMWaterMark); + Ret = printAppend(buffer, count, Ret, + "\n", + g_SysRAMHighWaterMark); + Ret = printAppend(buffer, count, Ret, + "\n", + g_IOMemWaterMark); + Ret = printAppend(buffer, count, Ret, + "\n", + g_IOMemHighWaterMark); + + Ret = printAppend(buffer, count, Ret, "\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, "\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 + "\n" + "\t%s\n" + "\t%-8p\n" + "\t%08lx\n" + "\t%ld\n" + "\t%d\n" + "\t%s\n" + "\t%s\n" + "\t%ld\n" "\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 + "\n" + "\t%s\n" + "\t%-8p\n" + "\t%08lx\n" + "\t%ld\n" + "\t%d\n" + "\t%s\n" + "\t%s\n" + "\t%ld\n" "\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 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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef __IMG_LINUX_MM_H__ +#define __IMG_LINUX_MM_H__ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#include + +#include + +#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 index 0000000..8c5b2e5 --- /dev/null +++ b/pvr/mmap.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) +#include +#endif +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) +#include +#include +#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 + "\n" + "\t%lu\n" + "\t%lu\n" "\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 + "\n" + "\t%-8p\n" + "\t%-8p\n" + "\t%08lx\n" + "\t%08lx\n" + "\t%-8ld\n" + "\t%-24s\n" + "\t%-5d\n" + "\t%-8s\n" + "\t%-5u\n" + "\t%08lx\n" + "\t%s\n" + "\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 index 0000000..0bebc53 --- /dev/null +++ b/pvr/mmap.h @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#if !defined(__MMAP_H__) +#define __MMAP_H__ + +#include + +#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 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. + * 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 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. + * 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 index 0000000..2084705 --- /dev/null +++ b/pvr/module.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(LDM_PLATFORM) +#include +#endif + +#if defined(LDM_PCI) +#include +#endif + +#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) +#include +#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 +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 index 0000000..33eed37 --- /dev/null +++ b/pvr/modules.order @@ -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 index 0000000..6381282 --- /dev/null +++ b/pvr/mutex.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +#include +#else +#include +#endif +#include + +#include +#include + +#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 index 0000000..41223f6 --- /dev/null +++ b/pvr/mutex.h @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef __INCLUDED_LINUX_MUTEX_H_ +#define __INCLUDED_LINUX_MUTEX_H_ + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +#include +#else +#include +#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 index 0000000..9225b0d --- /dev/null +++ b/pvr/oemfuncs.h @@ -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. + * 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 index 0000000..d10cdd7 --- /dev/null +++ b/pvr/omaplfb.h @@ -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. + * 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 index 0000000..55e6f81 --- /dev/null +++ b/pvr/omaplfb_displayclass.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..fa96a19 --- /dev/null +++ b/pvr/omaplfb_linux.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#if defined(LDM_PLATFORM) +#include +#endif + +#include "img_defs.h" +#include "servicesext.h" +#include "kerneldisplay.h" +#include "omaplfb.h" +#include "pvrmodule.h" + +#if defined (SUPPORT_TI_DSS_FW) +#include +#include +#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 +#include +#include +#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 index 0000000..8370e1a --- /dev/null +++ b/pvr/osfunc.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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(¤t->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(¤t->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(¤t->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(¤t->mm->mmap_sem); + iNumPagesMapped = + get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, + 1, 0, psInfo->ppsPages, NULL); + up_read(¤t->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(¤t->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(¤t->mm->mmap_sem); + +exit_check: + CheckPagesContiguous(psInfo); + + *phOSWrapMem = (IMG_HANDLE) psInfo; + + return PVRSRV_OK; + +error_release_mmap_sem: + up_read(¤t->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 index 0000000..f8b91e9 --- /dev/null +++ b/pvr/osfunc.h @@ -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. + * 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 +#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 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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include + +#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 index 0000000..59c6996 --- /dev/null +++ b/pvr/pdump.c @@ -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. + * 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 + +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 index 0000000..988f105 --- /dev/null +++ b/pvr/pdump_km.h @@ -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. + * 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 index 0000000..3515fa3 --- /dev/null +++ b/pvr/pdumpdefs.h @@ -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. + * 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 index 0000000..f0cd7dd --- /dev/null +++ b/pvr/perproc.c @@ -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. + * 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 index 0000000..8c4d61d --- /dev/null +++ b/pvr/perproc.h @@ -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. + * 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 index 0000000..00a7957 --- /dev/null +++ b/pvr/power.c @@ -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. + * 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 index 0000000..a3fefd9 --- /dev/null +++ b/pvr/power.h @@ -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. + * 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 index 0000000..f19a189 --- /dev/null +++ b/pvr/proc.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#include +#include +#include + +#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 index 0000000..f00823e --- /dev/null +++ b/pvr/proc.h @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef __SERVICES_PROC_H__ +#define __SERVICES_PROC_H__ + +#include +#include + +#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 index 0000000..abbe9c7 --- /dev/null +++ b/pvr/pvr_bridge.h @@ -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. + * 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 + +#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 index 0000000..bf668fb --- /dev/null +++ b/pvr/pvr_bridge_k.c @@ -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. + * 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 index 0000000..a144092 --- /dev/null +++ b/pvr/pvr_bridge_km.h @@ -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. + * 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 index 0000000..f56b2a1 --- /dev/null +++ b/pvr/pvr_debug.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#include +#include +#include +#include +#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 index 0000000..3b0d026 --- /dev/null +++ b/pvr/pvr_debug.h @@ -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. + * 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 index 0000000..7b16554 --- /dev/null +++ b/pvr/pvrmmap.h @@ -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. + * 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 index 0000000..dcf517b --- /dev/null +++ b/pvr/pvrmodule.h @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifndef _PVRMODULE_H_ +#define _PVRMODULE_H_ +MODULE_AUTHOR("Imagination Technologies Ltd. "); +MODULE_LICENSE("GPL"); +#endif diff --git a/pvr/pvrsrv.c b/pvr/pvrsrv.c new file mode 100644 index 0000000..50e39e7 --- /dev/null +++ b/pvr/pvrsrv.c @@ -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. + * 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 index 0000000..aab880a --- /dev/null +++ b/pvr/pvrversion.h @@ -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. + * 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 index 0000000..9bb8360 --- /dev/null +++ b/pvr/queue.c @@ -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. + * 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 \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 index 0000000..687b36b --- /dev/null +++ b/pvr/queue.h @@ -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. + * 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 + 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 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. + * 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 +#include "proc.h" +#endif + +#ifdef USE_BM_FREESPACE_CHECK +#include +#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 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. + * 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 index 0000000..29bf9f1 --- /dev/null +++ b/pvr/regpaths.h @@ -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. + * 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 index 0000000..d503b0e --- /dev/null +++ b/pvr/resman.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include "services_headers.h" +#include "resman.h" + +#ifdef __linux__ +#ifndef AUTOCONF_INCLUDED +#include +#endif + +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) +#include +#else +#include +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#include +#else +#include +#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 index 0000000..1078f64 --- /dev/null +++ b/pvr/resman.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. + * 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 index 0000000..8e10c83 --- /dev/null +++ b/pvr/services.h @@ -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. + * 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 index 0000000..3e25dee --- /dev/null +++ b/pvr/services_headers.h @@ -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. + * 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 index 0000000..cd35306 --- /dev/null +++ b/pvr/servicesext.h @@ -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. + * 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 index 0000000..8ccdd45 --- /dev/null +++ b/pvr/servicesint.h @@ -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. + * 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 index 0000000..1a4b7a0 --- /dev/null +++ b/pvr/sgx530defs.h @@ -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. + * 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 index 0000000..521d2d4 --- /dev/null +++ b/pvr/sgx_bridge.h @@ -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. + * 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 index 0000000..86c5525 --- /dev/null +++ b/pvr/sgx_bridge_km.h @@ -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. + * 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 index 0000000..ea7ba9b --- /dev/null +++ b/pvr/sgxapi_km.h @@ -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. + * 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 +#else +#include +#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 index 0000000..5f0d4d2 --- /dev/null +++ b/pvr/sgxconfig.h @@ -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. + * 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 index 0000000..ff5f6b8 --- /dev/null +++ b/pvr/sgxcoretypes.h @@ -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. + * 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 index 0000000..f58ca26 --- /dev/null +++ b/pvr/sgxdefs.h @@ -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. + * 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 index 0000000..7a02d93 --- /dev/null +++ b/pvr/sgxerrata.h @@ -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. + * 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 index 0000000..78e0061 --- /dev/null +++ b/pvr/sgxfeaturedefs.h @@ -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. + * 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 index 0000000..8f0c407 --- /dev/null +++ b/pvr/sgxinfo.h @@ -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. + * 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 index 0000000..3c413a4 --- /dev/null +++ b/pvr/sgxinfokm.h @@ -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. + * 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 index 0000000..18bbe1f --- /dev/null +++ b/pvr/sgxinit.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include + +#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 index 0000000..4d192a7 --- /dev/null +++ b/pvr/sgxkick.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include +#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 index 0000000..8e688bf --- /dev/null +++ b/pvr/sgxmmu.h @@ -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. + * 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< + * 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 index 0000000..cccf28a --- /dev/null +++ b/pvr/sgxscript.h @@ -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. + * 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 index 0000000..df8d84a --- /dev/null +++ b/pvr/sgxtransfer.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#if defined(TRANSFER_QUEUE) + +#include + +#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 index 0000000..47ee31e --- /dev/null +++ b/pvr/sgxutils.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include + +#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 +#else +#include +#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 index 0000000..b66adc3 --- /dev/null +++ b/pvr/sgxutils.h @@ -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. + * 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 index 0000000..9cb58dd --- /dev/null +++ b/pvr/srvkm.h @@ -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. + * 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 index 0000000..d12e46e --- /dev/null +++ b/pvr/syscommon.h @@ -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. + * 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 +#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 index 0000000..6a6fa74 --- /dev/null +++ b/pvr/sysconfig.c @@ -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. + * 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 index 0000000..81ce9ad --- /dev/null +++ b/pvr/sysconfig.h @@ -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. + * 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 index 0000000..4d39be3 --- /dev/null +++ b/pvr/sysinfo.h @@ -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. + * 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 index 0000000..c541e7a --- /dev/null +++ b/pvr/syslocal.h @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#if !defined(__SYSLOCAL_H__) +#define __SYSLOCAL_H__ + +#if defined(__linux__) +#include +#include +#if defined (SUPPORT_TI_PM) +#include +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) +#include +#endif +#else +#include +#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 index 0000000..02c9831 --- /dev/null +++ b/pvr/sysutils.c @@ -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. + * 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 index 0000000..1d1e848 --- /dev/null +++ b/pvr/sysutils_linux.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#if defined (SUPPORT_TI_PM) +#include +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) +#include +#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 index 0000000..4004609 --- /dev/null +++ b/pvr/tools/dbgdriv.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifdef LINUX +#include +#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 index 0000000..020b59c --- /dev/null +++ b/pvr/tools/dbgdriv.h @@ -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. + * 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 index 0000000..036f649 --- /dev/null +++ b/pvr/tools/hostfunc.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..3e855de --- /dev/null +++ b/pvr/tools/hostfunc.h @@ -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. + * 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 index 0000000..4319020 --- /dev/null +++ b/pvr/tools/hotkey.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#if !defined(LINUX) +#include +#include +#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 index 0000000..5d18632 --- /dev/null +++ b/pvr/tools/hotkey.h @@ -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. + * 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 index 0000000..2ff9af9 --- /dev/null +++ b/pvr/tools/ioctl.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#ifdef LINUX +#include +#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 index 0000000..ea207a2 --- /dev/null +++ b/pvr/tools/ioctl.h @@ -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. + * 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 index 0000000..72a1245 --- /dev/null +++ b/pvr/tools/linuxsrv.h @@ -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. + * 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 index 0000000..a1445d1 --- /dev/null +++ b/pvr/tools/main.c @@ -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. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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. "); +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); -- 2.39.5